Passar funções e ligar componentes
Em onClick={addPair}, o valor fornecido é uma função que React pode chamar em resposta ao evento. Em onClick={addPair()}, a função é chamada enquanto a expressão JSX é calculada, e o valor devolvido é que é passado como prop. A diferença é de momento e contrato, não apenas de sintaxe.
AddPairButton recebe uma prop própria chamada onAddPair e liga-a explicitamente ao onClick do button. O nome personalizado pode refletir a intenção de negócio; não cria sozinho um evento nativo. Em revisões, segue a função desde o pai até ao elemento que recebe a interação.
Uma função não usada dentro do filho explica por que motivo um botão aparentemente configurado não produz a ação esperada.
Propagação e comportamento por omissão
Um clique num elemento filho pode propagar-se a um handler de um antecessor. stopPropagation permite impedir essa propagação posterior; não desfaz um handler de captura que já tenha sido executado. preventDefault trata outro contrato: cancela uma ação por omissão de um evento cancelável, como a navegação normal de uma submissão de formulário.
Não uses as duas operações como sinónimos. Num formulário com onSubmit, impedir a navegação pode ser necessário sem impedir que outra parte da árvore observe o evento. Num botão dentro de um cartão clicável, pode interessar limitar a propagação do clique.
O exemplo usa type="button" para não pedir implicitamente uma submissão quando for incluído num formulário.
O estado pertence ao snapshot do render
useState fornece o valor deste render e uma função para pedir a atualização. Depois de setQuantity(5), uma leitura de quantity no mesmo handler continua a usar o valor capturado quando o handler foi criado. Não existe uma espera curta que faça esse binding local passar a apontar para outro render.
Esta regra explica por que razão console.log logo após um setter pode mostrar o valor anterior sem que o setter tenha falhado. Para analisar um incidente, identifica o render de origem do callback e as expressões que ele avalia. Uma nova renderização pode criar outro handler com novas entradas, mas não reescreve as variáveis capturadas por um callback que já foi agendado.
Substituições e transformações numa fila
Um valor como setQuantity(quantity + 1) é calculado antes de ser entregue ao setter. Com quantity igual a 3, duas dessas chamadas pedem duas substituições por 4. Um updater n => n + 1 representa outra operação: recebe o estado pendente e devolve a transformação seguinte.
Dois updaters produzem 4 e depois 5. Também podes combinar operações, desde que interpretes a ordem: substituir por 10 e depois subtrair 3 num updater produz 7; colocar no fim uma substituição por 2 faz o resultado final ser 2. Para rever um excerto, escreve uma tabela mental com estado pendente, operação e resultado.
Não assumas que cada entrada da fila cria um estado intermédio visível no DOM.
Limites do batching e pureza dos updaters
React pode processar várias atualizações depois de o handler terminar, evitando apresentar resultados parciais de cada chamada. Isso não significa agrupar indiscriminadamente cliques intencionais separados. Uma atualização do primeiro clique pode desativar um botão antes de outro clique.
Este comportamento da interface não prova entrega única num servidor perante retries, falhas ou outras sessões. Mantém também os updaters puros: devolver n + 1 é um cálculo; enviar uma mensagem externa dentro da função acrescenta um efeito.
Em desenvolvimento, Strict Mode pode chamar um updater novamente e descartar um dos resultados. A correção é retirar o efeito do cálculo, não ajustar contagens para um número supostamente fixo de chamadas.
Callbacks adiados e o instante relevante
O timer do exemplo captura quantity do clique em Record selection. Se a interface mudar de 5 para 7 antes dos três segundos, a nota desse timer continua a indicar 5. Isso cumpre o requisito indicado no comentário: registar a seleção daquele clique.
Noutro produto, o requisito poderia ser agir sobre o valor mais recente; essa necessidade exige um desenho explícito, não a suposição de que o closure muda sozinho. Antes de corrigir um valor antigo, pergunta qual instante constitui a decisão do utilizador.
Vários timers e respostas fora de ordem introduzem outro problema, que este pequeno excerto não resolve. É necessário definir cancelamento, substituição ou aceitação por identidade quando esse comportamento fizer parte do âmbito.
Diagnóstico antes de escolher a alteração
Para um botão que não responde, verifica primeiro se o callback chega ao elemento nativo. Para uma quantidade que só sobe uma unidade, distingue substituições calculadas a partir do mesmo snapshot de transformações sucessivas. Para uma confirmação antiga, compara o instante capturado com o requisito funcional.
Estes sintomas não têm uma correção universal baseada em adicionar um timer, um Effect ou uma variável global. Mantém as premissas da análise visíveis: estado inicial, sequência de chamadas, existência de outras atualizações e efeitos externos.
Os casos desta aula fornecem esses factos e pedem uma decisão de escolha única ou múltipla. Ler e justificar o comportamento é suficiente; não é necessário executar JSX para responder.
import {useState} from 'react';
function AddPairButton({onAddPair}) {
return <button type="button" onClick={onAddPair}>Add pair</button>;
}
export default function QuantityReview() {
const [quantity, setQuantity] = useState(3);
const [note, setNote] = useState('No selection recorded');
function addPair() {
setQuantity(n => n + 1);
setQuantity(n => n + 1);
}
function recordSelection() {
// Contract: record the quantity selected at this click.
setTimeout(() => setNote(`Selected at click: ${quantity}`), 3000);
}
return <>
<p>Quantity: {quantity}</p>
<AddPairButton onAddPair={addPair} />
<button type="button" onClick={recordSelection}>Record selection</button>
<p>{note}</p>
</>;
}Partindo de 3, um clique em Add pair produz 5 pela composição de dois updaters. Se Record selection for clicado com 5 e depois a quantidade mudar para 7, o timer dessa confirmação conserva 5. O excerto ilustra um único timer observado; não define ordenação ou cancelamento de várias confirmações nem persistência num servidor.
Armadilhas comuns
Chamar um handler ao passá-lo; esperar que um setter mude a variável local; usar duas substituições para representar dois incrementos; enviar mensagens dentro de updaters; confundir stopPropagation com preventDefault.
Tópicos relacionados: Componentes, props e renderização pura · Estrutura do estado e identidade dos componentes · Effects, refs e sincronização externa
Cada handler usa o snapshot do render que o criou. Valores passados ao setter pedem substituição; updaters puros transformam o estado pendente. O significado correto de um callback adiado depende do instante que o contrato pretende preservar.
Referência: Passing event handlers · React 19.3.0; JSX