Eu tenho um objeto observável externo (ao componente) no qual desejo escutar alterações. Quando o objeto é atualizado, ele emite eventos de alteração e desejo renderizar novamente o componente quando qualquer alteração for detectada.
Com um nível superior, React.render
isso foi possível, mas dentro de um componente não funciona (o que faz algum sentido, pois o render
método retorna um objeto).
Aqui está um exemplo de código:
export default class MyComponent extends React.Component {
handleButtonClick() {
this.render();
}
render() {
return (
<div>
{Math.random()}
<button onClick={this.handleButtonClick.bind(this)}>
Click me
</button>
</div>
)
}
}
Clicar no botão chama internamente this.render()
, mas não é isso que realmente faz a renderização (você pode ver isso em ação porque o texto criado por {Math.random()}
não muda). No entanto, se eu simplesmente ligar em this.setState()
vez de this.render()
, funciona bem.
Portanto, acho que minha pergunta é: os componentes do React precisam ter um estado para serem renderizados novamente? Existe uma maneira de forçar o componente a atualizar sob demanda sem alterar o estado?
this.forceUpdate()
é a solução certa, enquanto o restante de todas as respostas e vários comentários são contra o usoforceUpdate()
. Será bom dizer que a pergunta ainda não obteve uma solução / resposta adequada?Respostas:
No seu componente, você pode ligar
this.forceUpdate()
para forçar uma nova renderização.Documentação: https://facebook.github.io/react/docs/component-api.html
fonte
this.forceUpdate()
não seja uma solução muito boa para o problema dos solicitantes, é a resposta correta para a pergunta colocada no título. Embora geralmente deva ser evitado, há situações em que forceUpdate é uma boa solução.shouldComponentUpdate()
tornar sua solução inútil.forceUpdate
deve ser evitado porque se desvia de uma mentalidade de reagir. Os documentos do React citam um exemplo de quandoforceUpdate
pode ser usado:No entanto, gostaria de propor a idéia de que mesmo com objetos profundamente aninhados,
forceUpdate
é desnecessário. Ao usar uma fonte de dados imutável, as alterações de rastreamento ficam baratas; uma mudança sempre resultará em um novo objeto, portanto, precisamos apenas verificar se a referência ao objeto foi alterada. Você pode usar a biblioteca JS imutável para implementar objetos de dados imutáveis em seu aplicativo.Alterar a chave do elemento que você deseja renderizar novamente funcionará. Defina o suporte de chave em seu elemento via estado e, em seguida, quando desejar atualizar o estado definido para ter uma nova chave.
Em seguida, ocorre uma alteração e você redefine a chave
Quero observar que isso substituirá o elemento em que a chave está sendo alterada. Um exemplo de onde isso pode ser útil é quando você tem um campo de entrada de arquivo que deseja redefinir após o upload de uma imagem.
Embora a verdadeira resposta à pergunta do OP fosse
forceUpdate()
, achei esta solução útil em diferentes situações. Também quero observar que, se você estiver usando,forceUpdate
poderá revisar seu código e verificar se há outra maneira de fazer as coisas.NOTA 1-9-2019:
O acima (alterar a chave) substituirá completamente o elemento. Se você estiver atualizando a chave para fazer as alterações, provavelmente há um problema em outro lugar no seu código. O uso
Math.random()
da chave recriará o elemento a cada renderização. Eu NÃO recomendaria atualizar a chave assim, pois o React usa a chave para determinar a melhor maneira de renderizar novamente as coisas.fonte
key
. Primeiro, sua intenção não é clara. Um leitor do seu código terá que trabalhar duro para entender por que você está usandokey
dessa maneira. Segundo, isso não é mais puro queforceUpdate
. Reagir "Puro" significa que a apresentação visual do seu componente é 100% dependente de seu estado; portanto, se você alterar qualquer estado, ele será atualizado. Se, no entanto, você tiver alguns objetos profundamente aninhados (o cenário em que osforceUpdate
documentos citam um motivo para usá-lo), o usoforceUpdate
deixa isso claro. Terceiro,Math.random()
é ... aleatório. Teoricamente, poderia gerar o mesmo número aleatório.forceUpdate
é a maneira React de fazer isso.Na verdade,
forceUpdate()
é a única solução correta, poissetState()
pode não acionar uma nova renderização se lógica adicional for implementadashouldComponentUpdate()
ou quando ela simplesmente retornarfalse
.forçar atualização()
setState ()
forceUpdate()
pode ser chamado de dentro do seu componentethis.forceUpdate()
Ganchos: como forçar o componente a renderizar novamente com ganchos no React?
BTW: Você está mudando de estado ou suas propriedades aninhadas não se propagam?
fonte
this.state
fora do construtor também deve gerar um erro. Pode não ter feito isso em 2016; mas tenho certeza de que faz isso agora.Evitei
forceUpdate
fazendo o seguinteportanto, ao fazer esse aprimoramento de código, seu componente será ÚNICO e renderizará naturalmente
fonte
this.state.rows.map((item) => <MyComponent item={item} key={item.id} /> )
Quando você deseja que dois componentes do React se comuniquem, que não estão vinculados a um relacionamento (pai-filho), é recomendável usar o Flux ou arquiteturas similares.
O que você deseja fazer é ouvir as alterações do armazenamento de
componentes observáveis, que mantém o modelo e sua interface, e salvar os dados que fazem com que a renderização seja alterada comostate
emMyComponent
. Quando a loja envia os novos dados, você altera o estado do seu componente, que aciona automaticamente a renderização.Normalmente você deve tentar evitar o uso
forceUpdate()
. A partir da documentação:fonte
react-redux
para mapear automaticamente o estado da loja para os componentes, sempre que necessário, com base na função de mapeamento fornecida.forceUpdate
use ganchos ou HOC faça a sua escolha
Usando ganchos ou o padrão HOC (componente de ordem superior) , você pode ter atualizações automáticas quando suas lojas mudarem. Essa é uma abordagem muito leve, sem uma estrutura.
useStore Hooks para lidar com as atualizações da loja
atualizações de armazenamento de manipulador do withStores HOC
Classe SimpleStore
Como usar
No caso de ganchos:
No caso do HOC:
Certifique-se de exportar suas lojas como um singleton para obter o benefício da mudança global da seguinte forma:
Essa abordagem é bastante simples e funciona para mim. Também trabalho em grandes equipes, uso o Redux e o MobX e acho que eles também são bons, mas com bastante clichê. Pessoalmente, gosto da minha própria abordagem, porque sempre odiei muito código para algo que pode ser simples quando você precisa.
fonte
this._data = {...this._data, ...newData}
.As outras respostas tentaram ilustrar como você poderia, mas o ponto é que você não deveria . Até a solução hacky de mudar a chave erra o alvo. O poder do React é abrir mão do controle de gerenciar manualmente quando algo deve renderizar e, em vez disso, apenas se preocupar com o modo como algo deve mapear as entradas. Em seguida, forneça o fluxo de insumos.
Se você precisar forçar a re-renderização manualmente, quase certamente não está fazendo algo certo.
fonte
Você pode fazer isso de duas maneiras:
1. Use o
forceUpdate()
método:Existem algumas falhas que podem ocorrer ao usar o
forceUpdate()
método. Um exemplo é que ele ignora oshouldComponentUpdate()
método e renderiza novamente a exibição, independentemente de oshouldComponentUpdate()
retorno ser falso. Por esse motivo, o uso de forceUpdate () deve ser evitado quando possível.2. Passando this.state para o
setState()
métodoA seguinte linha de código supera o problema com o exemplo anterior:
Realmente, tudo o que isto está fazendo é sobrescrever o estado atual pelo estado atual que aciona uma nova renderização. Essa ainda não é necessariamente a melhor maneira de fazer as coisas, mas supera algumas das falhas que você pode encontrar usando o método forceUpdate ().
fonte
this.setState(prevState => prevState);
Existem algumas maneiras de renderizar novamente seu componente:
A solução mais simples é usar o método forceUpdate ():
Mais uma solução é criar uma chave não usada no estado (nonUsedKey) e chamar a função setState com a atualização dessa nonUsedKey:
Ou reescreva todo o estado atual:
A alteração de adereços também fornece a renderização de componentes novamente.
fonte
Para garantir a integridade, você também pode conseguir isso em componentes funcionais:
Ou, como um gancho reutilizável:
Consulte: https://stackoverflow.com/a/53215514/2692307
Observe que o uso de um mecanismo de atualização de força ainda é uma prática ruim, pois contraria a mentalidade de reação, portanto, ainda deve ser evitado, se possível.
fonte
Podemos usar this.forceUpdate () como abaixo.
A parte do elemento 'Math.random' no DOM só é atualizada mesmo se você usar o setState para renderizar novamente o componente.
Todas as respostas aqui estão corretas, complementando a questão da compreensão ... como sabemos re-renderizar um componente sem usar o setState ({}), é usando o forceUpdate ().
O código acima é executado com setState como abaixo.
fonte
Apenas mais uma resposta para fazer backup da resposta aceita :-)
React desencoraja o uso de,
forceUpdate()
porque eles geralmente têm uma abordagem muito "esta é a única maneira de fazê-lo" em relação à programação funcional. Isso é bom em muitos casos, mas muitos desenvolvedores do React vêm com um background OO e, com essa abordagem, é perfeitamente aceitável ouvir um objeto observável.E se o fizer, você provavelmente sabe que DEVE renderizar novamente quando o observável "disparar" e, portanto, você DEVE usar
forceUpdate()
e é realmente uma vantagem queshouldComponentUpdate()
NÃO está envolvida aqui.Ferramentas como MobX, que usa uma abordagem OO, estão fazendo isso na superfície (na verdade, o MobX chama
render()
diretamente)fonte
Eu achei melhor evitar forceUpdate (). Uma maneira de forçar a nova renderização é adicionar a dependência de render () a uma variável externa temporária e alterar o valor dessa variável conforme e quando necessário.
Aqui está um exemplo de código:
Chame this.forceChange () quando precisar forçar a nova renderização.
fonte
ES6 - Estou incluindo um exemplo que foi útil para mim:
Em uma "declaração curta", você pode passar uma função vazia como esta:
Esta parece ser a abordagem mais curta.
fonte
forceUpdate();
método funcionará, mas é aconselhável usarsetState();
fonte
Para realizar o que você está descrevendo, tente this.forceUpdate ().
fonte
Outra maneira está chamando
setState
, e preservar estado:this.setState(prevState=>({...prevState}));
fonte
forceUpdate (), mas toda vez que ouvi alguém falar sobre isso, foi seguido por você nunca deve usar isso.
fonte
Você pode usar forceUpdate () para obter mais detalhes, verifique ( forceUpdate () ).
fonte