Eventos
Você criou um botão. Agora ele precisa fazer algo de verdade quando alguém clica nele, salva um formulário, abre um menu, deleta um item. React lida com isso do mesmo jeito que lida com tudo mais: através de props. Em vez de chamar addEventListener como você fez no capítulo de eventos JavaScript, você passa uma função direto para uma prop no elemento que quer ouvir. A ideia é a mesma, uma função que executa quando algo acontece, mas a forma como você conecta tudo é um padrão React próprio.
Anexando um manipulador
function SaveButton() {
function handleClick() {
console.log('clicked')
}
return <button onClick={handleClick}>Save</button>
}Props de eventos são nomeadas em camelCase, correspondendo ao evento que ouvem: onClick para cliques, onChange quando o valor de um campo muda, onSubmit quando um formulário é enviado. Você escreve a prop no elemento e passa uma função para executar.
handleClick é definida dentro do componente e depois passada para onClick. React a chama sempre que o botão é clicado. Você está passando a função pelo nome, handleClick. Chamá-la, handleClick(), a executaria imediatamente, durante a renderização. Você está entregando a função para React executar depois, não executando você agora.
Quando você precisa de detalhes sobre o que aconteceu, React passa para seu manipulador um objeto de evento com as mesmas propriedades familiares, target, preventDefault(), e assim por diante, que você esperaria de addEventListener. Nomeie um parâmetro para capturá-lo, convencionalmente event:
function SearchBox() {
function handleChange(event) {
console.log(event.target.value)
}
return <input onChange={handleChange} />
}event.target é o elemento em que o evento foi disparado, e event.target.value é o texto atual no campo. Você só precisa recorrer ao objeto de evento quando um manipulador realmente precisa dessa informação. O onClick de um botão frequentemente não precisa.
O erro mais comum
Como o manipulador é uma função que você está passando para uma prop, esse é um erro que pega quase todo mundo em algum momento:
// Errado: executa handleClick imediatamente, enquanto o componente renderiza
<button onClick={handleClick()}>Save</button>
// Certo: passa a função em si, React a chama depois, no clique
<button onClick={handleClick}>Save</button>Os parênteses fazem toda a diferença. handleClick() executa a função ali mesmo, durante a renderização, e o que quer que ela retorne (geralmente undefined) é o que acaba em onClick. handleClick passa para React a função em si, para chamar sempre que o clique realmente acontecer. Se um manipulador parece disparar por conta própria no momento em que a página carrega, quase sempre é por isso.
Passando manipuladores como props
Um manipulador não precisa viver no mesmo componente que o elemento ao qual está anexado. Você pode defini-lo em um componente pai e passá-lo para um filho como uma prop, do mesmo jeito que passaria qualquer outro valor:
function SaveButton({ onSave }) {
return <button onClick={onSave}>Save</button>
}
function Form() {
function handleSave() {
console.log('saved')
}
return <SaveButton onSave={handleSave} />
}Form é dona de handleSave e a passa para SaveButton sob o nome da prop onSave. SaveButton não sabe nem se importa com o que a função faz, ela apenas a conecta a onClick. É assim que um clique em um componente pequeno e reutilizável acaba disparando lógica que vive mais acima na sua app, perto do estado ou dados que essa lógica precisa.
Evitando o comportamento padrão
Alguns eventos vêm com comportamentos do navegador anexados, e enviar um formulário é o que você encontrará primeiro. Por padrão, enviar um formulário recarrega a página, o que descarta tudo o que seu componente estava fazendo. Chame event.preventDefault() dentro do manipulador para impedir isso:
function SignupForm() {
function handleSubmit(event) {
event.preventDefault()
console.log('form submitted')
}
return (
<form onSubmit={handleSubmit}>
<input type="email" />
<button type="submit">Sign up</button>
</form>
)
}Anexe onSubmit ao <form> em si, não onClick ao botão. Dessa forma, pressionar Enter dentro do campo envia o formulário também, não só clicar no botão.
onClick e onChange, e você passa uma função para executar, não o resultado de executá-la. Escreva onClick={handleClick}, nunca onClick={handleClick()}. Quando um manipulador precisa de detalhes sobre o que aconteceu, capture-os com um parâmetro nomeado event.
Próximo: Renderização condicional, onde o que um componente retorna passa a depender dos dados que ele tem.

