Eventos
Você construiu um botão. Agora ele precisa fazer algo de verdade quando alguém clica nele, salvar um formulário, abrir um menu, deletar um item. React lida com isso da mesma forma que lida com tudo mais: através de props. Em vez de chamar addEventListener como você fez no capítulo de eventos do JavaScript, você passa uma função diretamente para uma prop no elemento que quer escutar. A ideia é a mesma — uma função que executa quando algo acontece — mas a forma de conectar tudo é um padrão React específico.
Anexando um manipulador
function SaveButton() {
function handleClick() {
console.log('clicado')
}
return <button onClick={handleClick}>Salvar</button>
}Props de eventos são nomeadas em camelCase, correspondendo ao evento que escutam: onClick para cliques, onChange para mudanças no valor de um campo, onSubmit para envio de formulário. Você escreve a prop no elemento e atribui uma função para executar.
handleClick é definida dentro do componente e 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 ela mesmo agora.
Quando você precisa de detalhes sobre o que aconteceu, React passa para seu manipulador um objeto de evento com as mesmas propriedades familiares que você esperaria de addEventListener, como target, preventDefault() e assim por diante. 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 disparou, e event.target.value é o texto atual no campo. Você só precisa chegar 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á entregando a uma prop, este é um erro que pega quase todo mundo em algum momento:
// Errado: executa handleClick imediatamente, enquanto o componente renderiza
<button onClick={handleClick()}>Salvar</button>
// Correto: passa a função em si, React a chama depois, no clique
<button onClick={handleClick}>Salvar</button>Os parênteses fazem toda a diferença. handleClick() executa a função bem ali, durante a renderização, e tudo que ela retorna (geralmente undefined) é o que acaba em onClick. handleClick entrega a função em si para React chamar sempre que o clique realmente acontecer. Se um manipulador parece disparar sozinho assim 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 em que está anexado. Você pode defini-lo em um componente pai e passá-lo para um filho como uma prop, da mesma forma que passaria qualquer outro valor:
function SaveButton({ onSave }) {
return <button onClick={onSave}>Salvar</button>
}
function Form() {
function handleSave() {
console.log('salvo')
}
return <SaveButton onSave={handleSave} />
}Form é dona de handleSave e a passa para SaveButton sob o nome de 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 aplicação, mais perto do state ou dos dados que essa lógica precisa.
Prevenindo o comportamento padrão
Alguns eventos vêm com comportamento do navegador anexado, e enviar um formulário é o que você encontrará primeiro. Por padrão, enviar um formulário recarrega a página, o que destrói tudo o que seu componente estava fazendo. Chame event.preventDefault() dentro do manipulador para parar isso:
function SignupForm() {
function handleSubmit(event) {
event.preventDefault()
console.log('formulário enviado')
}
return (
<form onSubmit={handleSubmit}>
<input type="email" />
<button type="submit">Se inscrever</button>
</form>
)
}Anexe onSubmit ao <form> em si, não onClick ao botão. Assim pressionar Enter dentro do campo também envia o formulário, não apenas clicar no botão.
onClick e onChange, e você atribui 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 começa a depender dos dados que ele tem.

