Ao terminar esta aula, você vai conseguir
- Associar funções a eventos no JSX
- Atualizar estado com base no valor anterior
- Manter objetos de estado imutáveis
Você clica em “Adicionar”, mas a quantidade não muda. Ou clica várias vezes e o número avança menos do que esperava. Em outro teste, o valor parece certo, mas um objeto antigo também foi alterado. Esses sintomas diferentes costumam nascer do mesmo ponto: a interface ainda não separou bem o que aconteceu de qual informação precisa mudar.
No React, um evento avisa que algo aconteceu — por exemplo, um clique. O estado guarda a informação que a tela precisa lembrar entre uma interação e outra. A gente precisa dos dois porque uma tela útil não apenas recebe ações: ela também conserva o resultado dessas ações e renderiza a versão mais recente.
Essa dupla aparece em produtos que você já conhece. Na reconstrução do Facebook.com com React, a equipe da Meta descreveu decisões de navegação e abas de conversa guiadas pelo estado da aplicação. O nosso contador é menor, mas ensina o mesmo caminho: interação, atualização e nova tela.
Se JSX ainda parece novo, volte à aula de componentes, JSX e Vite. Se a dúvida está em como um componente recebe uma ação de outro, revise props e composição.
Por que um botão precisa de evento e estado?
Porque o evento identifica a ação do usuário, enquanto o estado registra o dado que deve sobreviver ao clique. Sem o evento, o componente não sabe quando agir. Sem o estado, ele não tem uma memória própria para atualizar e mostrar.
Pense no placar de uma partida. O botão do operador é o evento; a pessoa que
interpreta esse botão faz o papel do handler, a função responsável por tratar
a ação; o número registrado é o estado; e o painel iluminado é a interface
renderizada. Quando o operador pede “some um”, o sistema atualiza o registro e
mostra outro placar. No React, essa solicitação passa pelo setter, a função de
atualização devolvida por useState.
A comparação tem um limite: o placar físico parece trocar na mesma hora, mas o React pode enfileirar e agrupar solicitações antes da próxima renderização. Por isso, estado não deve ser tratado como uma variável comum que muda imediatamente no meio da função.
Como fazer o primeiro clique atualizar a tela?
Comece pelo menor exemplo útil: um botão que conta cliques. Ele isola a relação entre evento, estado e nova renderização sem misturar regras de carrinho, validação ou formulário.
function Contador() {
const [total, setTotal] = React.useState(0);
function incrementar() {
setTotal(total + 1);
}
const eventos = { onClick: incrementar };
return (
<button type="button" {...eventos}>
Cliques: {total}
</button>
);
}Leia o exemplo de cima para baixo. Contador é o componente. useState(0) cria
o estado inicial 0 e devolve um par: total, que é o valor disponível nesta
renderização, e setTotal, que solicita a próxima versão. A função incrementar
é o handler; ela pede um total uma unidade maior.
O objeto eventos guarda a propriedade onClick apontando para o handler. No
botão, {...eventos} espalha essa propriedade no JSX; o resultado prático é o
mesmo vínculo entre o clique e incrementar. type="button" evita que o botão
envie um formulário por acidente, e {total} coloca o snapshot atual no texto.
Quando setTotal é chamado, React renderiza novamente e esse texto recebe o
novo valor. O artigo de eventos no React aprofunda
onClick, onChange e o objeto do evento.
Por que três setters podem somar apenas uma vez?
Porque cada renderização entrega um snapshot, uma fotografia do estado
naquele momento. Dentro do mesmo handler, total continua com o valor daquela
fotografia. Se três atualizações calcularem total + 1, as três podem partir do
mesmo número, em vez de formar uma sequência.
Quando o próximo estado depende do anterior, passe ao setter uma função atualizadora:
function somarTres() {
setTotal((atual) => atual + 1);
setTotal((atual) => atual + 1);
setTotal((atual) => atual + 1);
}Aqui, somarTres reúne três solicitações na mesma ação. Em cada chamada,
atual não vem do snapshot fechado no começo do handler: ele representa o valor
pendente mais recente da fila. A primeira função soma um, a segunda recebe esse
resultado e soma outro, e a terceira repete o processo. Assim, um clique nessa
ação produz um acréscimo de três.
Não use a forma funcional por ritual. Use quando o cálculo realmente depende do valor anterior, como incrementar, alternar um booleano ou atualizar um item a partir da coleção atual. Se o novo estado é um valor independente, o setter pode recebê-lo diretamente.
Como atualizar um objeto sem apagar ou corromper dados?
Crie um novo objeto para o próximo estado. O nome técnico dessa regra é imutabilidade: em vez de modificar o valor que pertence ao snapshot atual, a gente produz outra referência com a mudança desejada.
O terceiro exemplo mostra o erro:
item.quantidade += 1;
setItem(item);Na primeira linha, += 1 altera quantidade dentro do próprio objeto item.
Na segunda, setItem(item) entrega ao React a mesma referência que já estava no
estado. Além de dificultar a identificação da mudança, a alteração também
contamina o snapshot anterior. Quando esse padrão aparece, não é seguro concluir
que a tela sempre produzirá um resultado específico; o problema é justamente o
comportamento deixar de ser previsível.
O quarto exemplo faz a correção criando um objeto novo:
setItem((atual) => ({
...atual,
quantidade: atual.quantidade + 1,
}));setItem recebe uma função porque a nova quantidade depende do objeto atual.
Os parênteses depois da seta permitem devolver o objeto diretamente. O spread
...atual copia as propriedades existentes, e quantidade vem depois para
substituir somente essa propriedade. O resultado é uma nova referência com o
mesmo nome e a quantidade seguinte.
Essa cópia é rasa: se houvesse um objeto dentro de item, o nível interno
alterado também precisaria ser recriado. Muitas camadas podem ser um sinal de que
o estado deve ser simplificado. Veja mais casos com arrays e objetos em estado
imutável no React.
Como levar o contador mínimo para um carrinho?
O contador ensinou uma regra isolada. O laboratório transforma essa regra em
uma funcionalidade reconhecível: a quantidade de uma camiseta no carrinho.
item reúne nome e quantidade; aumentar e diminuir são handlers; as duas
funções usam o objeto mais recente e devolvem outro objeto. Em diminuir,
Math.max protege o limite mínimo. Os dois botões passam referências de função
ao onClick, sem executá-las durante a renderização.
O parágrafo com aria-live="polite" anuncia mudanças de quantidade para
tecnologias assistivas sem interromper a pessoa. Isso mostra a subida do exemplo
mínimo para uma decisão de produto: não basta o número mudar; a interação precisa
respeitar limites e comunicar o resultado.
Guarde somente o estado necessário. Se o subtotal sempre é preço vezes quantidade, calcule-o durante a renderização. Salvar quantidade e subtotal cria duas fontes de verdade que podem divergir. Essa mesma regra volta quando você construir um formulário controlado: o estado deve representar o dado, não cópias desnecessárias dele.
Por que o evento pode disparar antes do clique?
Ao escrever onClick={incrementar()}, os parênteses chamam a função durante a
renderização. O evento deixa de receber uma função para usar no clique; se essa
chamada agenda estado, outra renderização pode chamar tudo novamente. O conserto
é passar a referência onClick={incrementar}. Para reconhecer o erro, olhe
primeiro para o valor entregue ao onClick: precisa ser uma função, não o
resultado de uma chamada.
Outro erro é mutar objeto ou array e depois passar a mesma referência ao setter.
O conserto é criar o próximo valor com spread, map ou filter, conforme o tipo
de dado. Não decore uma ferramenta isolada; procure a regra: o snapshot atual
permanece intacto e o próximo estado recebe uma nova referência.
O que você leva para a próxima aula?
- Evento informa o que aconteceu; handler decide a atualização.
- Estado é a memória da interface naquela renderização.
- Função atualizadora é a escolha segura quando o próximo valor depende do anterior.
- Objetos e arrays de estado são substituídos, não mutados.
- Valores derivados, como subtotal, não precisam virar outro estado.
Feche com a missão do placar: cinco cliques rápidos devem produzir 5; zerar
deve produzir 0; repetir a sequência não pode perder cliques; e nenhuma
atualização pode modificar diretamente um objeto de estado. Esse teste verifica
comportamento, não uma saída inventada.
Na aula 4, você aplicará o mesmo raciocínio a uma coleção: criar um novo array, preservar a identidade de cada item e derivar filtros. Continue em listas, filtros e keys.
Laboratório ao vivo
Controle de quantidade do carrinho
Use os botões para alterar a quantidade. Depois limite o máximo a cinco e confirme que diminuir em zero nunca produz valor negativo.
Pare e pense
Quando o próximo estado depende do estado anterior, qual forma é mais segura?
A função atualizadora recebe o estado pendente mais recente. Isso evita usar um snapshot antigo quando várias atualizações são enfileiradas.
Faça sem copiar
Construa um placar com botões +1 e zerar. A missão passa se cinco cliques rápidos produzem 5, zerar produz 0 e nenhum objeto de estado é alterado diretamente.
Fontes para consultar
Terminou a missão?
Marque apenas quando você conseguir explicar o conceito e concluir o desafio. O progresso fica salvo somente neste navegador.
Próxima: Listas, keys e filtros no React →