Compreender Reat ‘setState’
Reat components can, and often do, have state. Estado pode ser qualquer coisa, mas pense em coisas como se um usuário está logado ou não e exibindo o nome de usuário correto com base em que conta está ativa. Ou uma série de posts no blog. Ou se um modal está aberto ou não e qual aba dentro dele está ativo.
reaja components with state render UI based on that state. Quando o estado dos componentes muda, o mesmo acontece com a UI componente. Isso torna importante compreender quando e como mudar o estado do seu componente. No final deste tutorial, você deve saber como setState
funciona, e ser capaz de evitar armadilhas comuns que muitos de nós atingir quando a aprendizagem reage.
o funcionamento de`setState () ‘
setState()
é a única forma legítima de atualizar o estado após a configuração inicial do estado. Digamos que temos um componente de pesquisa e queremos exibir o termo de pesquisa que um usuário submete.
Aqui está a configuração:
import React, { Component } from 'react'class Search extends Component { constructor(props) { super(props) state = { searchTerm: '' } }}
Estamos passando uma seqüência vazia como um valor e, para actualizar o estado de searchTerm
, temos que chamar setState()
.
setState({ searchTerm: event.target.value })
Aqui, estamos passando um objeto para setState()
. O objeto contém a parte do Estado que queremos atualizar que, neste caso, é o valor de searchTerm
. Reat pega este valor e funde-o no objeto que precisa dele. É uma espécie de como o Search
componente pergunta o que ele deve usar para o valor de searchTerm
e setState()
responde com uma resposta.
isto é basicamente iniciar um processo que reage chama reconciliação. O processo de reconciliação é a forma como reagem atualiza o DOM, fazendo alterações ao componente com base na mudança de Estado. Quando o pedido para setState()
é despoletado, Reat cria uma nova árvore contendo os elementos reativos no componente (juntamente com o estado atualizado). Esta árvore é usada para descobrir como o UI do componenteSearch
deve mudar em resposta à mudança de Estado, comparando-o com os elementos da árvore anterior. Reat sabe quais as alterações a implementar e só actualizará as partes do DOM quando necessário. É por isso que a reacção é rápida.
isso soa muito, mas para resumir o fluxo:
- Nós temos um componente de pesquisa que apresenta um termo de pesquisa
- Que o termo de pesquisa é de momento vazio
- O usuário envia um termo de pesquisa
- o termo é capturado e armazenado por
setState
valor - a Reconciliação acontece e Reagir percebe a alteração no valor
- Reagir instrui o componente de pesquisa para atualizar o valor e o termo de pesquisa é intercaladas
O processo de reconciliação não, necessariamente, de mudar toda árvore, exceto em uma situação onde a raiz da árvore é alterado como este:
// old<div> <Search /></div>// new<span> <Search /></span>
Todos <div>
tags tornam <span>
tags e toda a componente árvore vai ser atualizado como resultado.
A regra geral é nunca mutar o estado diretamente. Utilizar sempre setState()
para mudar de Estado. Modificar o estado diretamente, como o excerto abaixo não fará com que o componente volte a renderizar.
// do not do thisthis.state = { searchTerm: event.target.value}
passando uma função para `setState ()`
para demonstrar mais esta ideia, vamos criar um contador simples que aumenta e diminui ao clicar.
See the Pen setState Pen by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.
let’s register the component and definite the markup for the UI:
class App extends React.Component {state = { count: 0 }handleIncrement = () => { this.setState({ count: this.state.count + 1 })}handleDecrement = () => { this.setState({ count: this.state.count - 1 })} render() { return ( <div> <div> {this.state.count} </div> <button onClick={this.handleIncrement}>Increment by 1</button> <button onClick={this.handleDecrement}>Decrement by 1</button> </div> ) }}
neste ponto, o contador simplesmente aumenta ou diminui a contagem em 1 em cada clique. mas e se quiséssemos aumentar ou diminuir em 3? Poderíamos tentar chamar setState()
três vezes o handleDecrement
e handleIncrement
funções como este:
handleIncrement = () => { this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 })}handleDecrement = () => { this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 })}
Se estiver a codificar em casa, poderá ficar surpreendido por ver que isso não funciona.
O trecho de código acima é equivalente a:
Object.assign( {}, { count: this.state.count + 1 }, { count: this.state.count + 1 }, { count: this.state.count + 1 },)
Object.assign()
é usado para copiar dados de um objecto de origem de um objeto de destino. Se os dados que estão sendo copiados da fonte para o alvo todos têm as mesmas chaves, como no nosso exemplo, o último objeto ganha. Aqui está uma versão mais simples de como Object.assign()
funciona;
let count = 3const object = Object.assign({}, {count: count + 1}, {count: count + 2}, {count: count + 3});console.log(object);// output: Object { count: 6 }
assim, em vez de a chamada acontecer três vezes, acontece apenas uma vez. Isto pode ser corrigido passando uma função para setState()
. Assim como você passa objetos para setState()
, Você também pode passar funções, e essa é a maneira de sair da situação acima.
Se editarmos a função handleIncrement
para ficar assim:
handleIncrement = () => { this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 }))}
…podemos agora contar de incrementos três vezes com um clique.
neste caso, em vez de se fundir, reaja filas de espera da função na ordem em que são feitas e atualiza as de estado inteiro que é feito. Isto atualiza o estado de contagem para 3 em vez de 1.
acesse o estado anterior usando o Updater
quando construir aplicações Reat, há momentos em que você vai querer calcular o estado baseado no estado anterior do componente. Você nem sempre pode confiar em this.state
para manter o estado correto imediatamente após chamar setState()
, pois é sempre igual ao Estado representado na tela. vamos voltar ao nosso contra-exemplo para ver como isto funciona. Digamos que temos uma função que decreta a nossa contagem por 1. Esta função parece-se com esta:
changeCount = () => { this.setState({ count: this.state.count - 1})}
o que queremos é a capacidade de decremento por 3. A função changeCount()
é chamada três vezes em uma função que lida com o evento click, assim.
handleDecrement = () => { this.changeCount() this.changeCount() this.changeCount()}
cada vez que o botão para decrementar é clicado, a contagem irá decrement por 1 em vez de 3. Isto porque o this.state.count
não é atualizado até que o componente tenha sido re-renderizado. A solução é usar um updater. Um updater lhe permite acessar o estado atual e colocá-lo a usar imediatamente para atualizar outros itens. Assim, a função changeCount()
será assim.
changeCount = () => { this.setState((prevState) => { return { count: prevState.count - 1} })}
Now we are not depending on the result ofthis.state
. Os estados de count
são construídos uns sobre os outros para que possamos acessar o estado correto que muda com cada chamada parachangeCount()
.
setState()
deve ser tratado de forma assíncrona — por outras palavras, nem sempre espere que o estado tenha mudado depois de chamarsetState()
.
Quebra automática
Ao trabalhar com setState()
, estas são as principais coisas que você deve saber:
- Atualização para o estado de um componente deve ser feito usando
setState()
- Você pode passar um objeto ou uma função de
setState()
- Passar uma função quando você pode atualizar o estado várias vezes
- não dependem desta.declare imediatamente após chamar
setState()
e faça uso da função updater em vez disso.