Estado como um Instantâneo
Variáveis de estado podem parecer variáveis JavaScript comuns que você pode ler e escrever. No entanto, o estado se comporta mais como um instantâneo. Definir o estado não altera a variável de estado que você já tem, mas sim dispara uma nova renderização.
Você aprenderá
- Como definir o estado dispara novas renderizações
- Quando e como as atualizações de estado ocorrem
- Por que o estado não é atualizado imediatamente após você defini-lo
- Como os manipuladores de eventos acessam um "instantâneo" do estado
Definir o estado dispara renderizações
Você pode pensar na sua interface de usuário como mudando diretamente em resposta a um evento do usuário, como um clique. No React, isso funciona um pouco diferente desse modelo mental. Na página anterior, você viu quedefinir o estado solicita uma nova renderizaçãodo React. Isso significa que, para uma interface reagir ao evento, você precisaatualizar o estado.
Neste exemplo, quando você pressiona "enviar",setIsSent(true)diz ao React para renderizar novamente a interface:
Aqui está o que acontece quando você clica no botão:
- O manipulador de eventos
onSubmité executado. setIsSent(true)defineisSentcomotruee coloca uma nova renderização na fila.- O React renderiza novamente o componente de acordo com o novo valor de
isSent.
Vamos dar uma olhada mais de perto na relação entre estado e renderização.
A renderização tira um instantâneo no tempo
"Renderização"significa que o React está chamando seu componente, que é uma função. O JSX que você retorna dessa função é como um instantâneo da interface em um momento específico. Suas props, manipuladores de eventos e variáveis locais foram todos calculadosusando o estado no momento da renderização.
Diferente de uma fotografia ou de um quadro de filme, o "instantâneo" da interface que você retorna é interativo. Ele inclui lógica como manipuladores de eventos que especificam o que acontece em resposta a entradas. O React atualiza a tela para corresponder a esse instantâneo e conecta os manipuladores de eventos. Como resultado, pressionar um botão acionará o manipulador de clique do seu JSX.
Quando o React renderiza novamente um componente:
- O React chama sua função novamente.
- Sua função retorna um novo instantâneo JSX.
- O React então atualiza a tela para corresponder ao instantâneo que sua função retornou.
O React executando a função
Calculando o instantâneo
Atualizando a árvore DOM
Ilustrado porRachel Lee Nabors
Como memória de um componente, o estado não é como uma variável comum que desaparece após sua função retornar. O estado realmente "vive" no próprio React — como se estivesse em uma prateleira! — fora da sua função. Quando o React chama seu componente, ele fornece um instantâneo do estado para aquela renderização específica. Seu componente retorna um instantâneo da interface com um novo conjunto de props e manipuladores de eventos em seu JSX, todos calculadosusando os valores de estado daquela renderização!
Você diz ao React para atualizar o estado
O React atualiza o valor do estado
O React passa um instantâneo do valor do estado para o componente
Ilustrado porRachel Lee Nabors
Aqui está um pequeno experimento para mostrar como isso funciona. Neste exemplo, você pode esperar que clicar no botão "+3" incremente o contador três vezes porque ele chamasetNumber(number + 1)três vezes.
Veja o que acontece quando você clica no botão "+3":
Observe quenumbersó incrementa uma vez por clique!
Definir o estado só o altera para apróximarenderização.Durante a primeira renderização,numberera0. É por isso que, no manipuladoronClick daquela renderizaçãoonClick, o valor denumberainda é0mesmo depois desetNumber(number + 1)ter sido chamado:
Eis o que o manipulador de clique deste botão diz ao React para fazer:
setNumber(number + 1):numberé0entãosetNumber(0 + 1).- O React se prepara para alterar
numberpara1na próxima renderização.
- O React se prepara para alterar
setNumber(number + 1):numberé0entãosetNumber(0 + 1).- O React se prepara para alterar
numberpara1na próxima renderização.
- O React se prepara para alterar
setNumber(number + 1):numberé0entãosetNumber(0 + 1).- O React se prepara para alterar
numberpara1na próxima renderização.
- O React se prepara para alterar
Embora você tenha chamadosetNumber(number + 1)três vezes, no manipulador de eventosdesta renderização, numberé sempre0, então você define o estado para1três vezes. É por isso que, após o manipulador de eventos terminar, o React renderiza novamente o componente comnumberigual a1em vez de3.
Você também pode visualizar isso substituindo mentalmente as variáveis de estado por seus valores no seu código. Como a variável de estadonumber é 0paraesta renderização, seu manipulador de eventos se parece com isto:
Para a próxima renderização,number é 1, então o manipulador de cliquedessa renderizaçãofica assim:
É por isso que clicar no botão novamente definirá o contador para2, depois para3no próximo clique, e assim por diante.
Estado ao longo do tempo
Bem, isso foi divertido. Tente adivinhar o que este botão irá alertar ao ser clicado:
Se você usar o método de substituição de antes, pode adivinhar que o alerta mostra "0":
Mas e se você colocar um temporizador no alerta, para que ele só disparedepoisdo componente ser renderizado novamente? Ele diria "0" ou "5"? Tente adivinhar!
Surpreso? Se você usar o método de substituição, pode ver o "instantâneo" do estado passado para o alerta.
O estado armazenado no React pode ter mudado no momento em que o alerta é executado, mas ele foi agendado usando um instantâneo do estado no momento em que o usuário interagiu com ele!
O valor de uma variável de estado nunca muda dentro de uma renderização,mesmo que o código do seu manipulador de eventos seja assíncrono. Dentro doonClick daquela renderizaçãoonClick, o valor denumbercontinua sendo0mesmo depois desetNumber(number + 5)ter sido chamado. Seu valor foi "fixado" quando o React "tirou o instantâneo" da UI ao chamar seu componente.
Aqui está um exemplo de como isso torna seus manipuladores de eventos menos propensos a erros de tempo. Abaixo está um formulário que envia uma mensagem com um atraso de cinco segundos. Imagine este cenário:
- Você pressiona o botão "Enviar", enviando "Olá" para Alice.
- Antes que o atraso de cinco segundos termine, você altera o valor do campo "Para" para "Bob".
O que você espera que oalertexiba? Ele exibiria "Você disse Olá para Alice"? Ou exibiria "Você disse Olá para Bob"? Faça um palpite com base no que você sabe e, em seguida, tente:
O React mantém os valores do estado “fixos” dentro dos manipuladores de eventos de uma renderização.Você não precisa se preocupar se o estado mudou enquanto o código está sendo executado.
Mas e se você quisesse ler o estado mais recente antes de uma nova renderização? Você vai querer usar umafunção de atualização de estado, abordada na próxima página!
Recapitulação
- Definir um estado solicita uma nova renderização.
- O React armazena o estado fora do seu componente, como se estivesse em uma prateleira.
- Quando você chama
useState, o React lhe dá um instantâneo do estadopara aquela renderização. - Variáveis e manipuladores de eventos não “sobrevivem” a re-renderizações. Cada renderização tem seus próprios manipuladores de eventos.
- Cada renderização (e as funções dentro dela) sempre “verá” o instantâneo do estado que o React deu paraaquelarenderização.
- Você pode substituir mentalmente o estado nos manipuladores de eventos, de forma semelhante a como você pensa sobre o JSX renderizado.
- Manipuladores de eventos criados no passado têm os valores do estado da renderização em que foram criados.
Experimente alguns desafios
Challenge 1 of 1:Implemente um semáforo #
Aqui está um componente de semáforo de pedestres que alterna quando o botão é pressionado:
Adicione um alert ao manipulador de clique. Quando a luz estiver verde e disser “Walk”, clicar no botão deve dizer “Stop is next”. Quando a luz estiver vermelha e disser “Stop”, clicar no botão deve dizer “Walk is next”.
Faz diferença se você colocar o alert antes ou depois da chamada setWalk?
