Respondendo a Eventos
O React permite que você adicionemanipuladores de eventosao seu JSX. Manipuladores de eventos são suas próprias funções que serão acionadas em resposta a interações como clicar, passar o mouse, focar em entradas de formulário e assim por diante.
Você aprenderá
- Diferentes maneiras de escrever um manipulador de eventos
- Como passar a lógica de manipulação de eventos de um componente pai
- Como os eventos se propagam e como pará-los
Adicionando manipuladores de eventos
Para adicionar um manipulador de eventos, você primeiro definirá uma função e depois apassará como uma proppara a tag JSX apropriada. Por exemplo, aqui está um botão que ainda não faz nada:
Você pode fazê-lo mostrar uma mensagem quando um usuário clicar seguindo estes três passos:
- Declare uma função chamada
handleClickdentrodo seu componenteButton. - Implemente a lógica dentro dessa função (use
alertpara mostrar a mensagem). - Adicione
onClick={handleClick}ao JSX do<button>.
Você definiu a funçãohandleClicke depois apassou como uma proppara o<button>.handleClické ummanipulador de eventos.As funções manipuladoras de eventos:
- Geralmente são definidasdentrodos seus componentes.
- Têm nomes que começam com
handle, seguido pelo nome do evento.
Por convenção, é comum nomear manipuladores de eventos comohandleseguido pelo nome do evento. Você frequentemente veráonClick={handleClick},onMouseEnter={handleMouseEnter}, e assim por diante.
Alternativamente, você pode definir um manipulador de evento inline no JSX:
Ou, de forma mais concisa, usando uma função de seta:
Todos esses estilos são equivalentes. Manipuladores de eventos inline são convenientes para funções curtas.
Armadilha
As funções passadas para manipuladores de eventos devem ser passadas, não chamadas. Por exemplo:
| passar uma função (correto) | chamar uma função (incorreto) |
|---|---|
<button onClick={handleClick}> | <button onClick={handleClick()}> |
A diferença é sutil. No primeiro exemplo, a funçãohandleClické passada como um manipulador de eventoonClick. Isso diz ao React para lembrá-la e chamar sua função apenas quando o usuário clicar no botão.
No segundo exemplo, o()no final dehandleClick()executa a funçãoimediatamentedurante arenderização, sem nenhum clique. Isso acontece porque o JavaScript dentro doJSX { e }é executado imediatamente.
Quando você escreve código inline, a mesma armadilha se apresenta de uma maneira diferente:
| passar uma função (correto) | chamar uma função (incorreto) |
|---|---|
<button onClick={() => alert('...')}> | <button onClick={alert('...')}> |
Passar código inline assim não será acionado no clique—ele é acionado toda vez que o componente renderiza:
Se você quiser definir seu manipulador de evento inline, envolva-o em uma função anônima assim:
Em vez de executar o código dentro a cada renderização, isso cria uma função para ser chamada posteriormente.
Em ambos os casos, o que você quer passar é uma função:
<button onClick={handleClick}>passa a funçãohandleClick.<button onClick={() => alert('...')}>passa a função() => alert('...').
Lendo props em manipuladores de eventos
Como os manipuladores de eventos são declarados dentro de um componente, eles têm acesso às props do componente. Aqui está um botão que, quando clicado, exibe um alerta com sua propmessage:
Isso permite que esses dois botões mostrem mensagens diferentes. Tente alterar as mensagens passadas para eles.
Passando manipuladores de eventos como props
Frequentemente, você vai querer que o componente pai especifique o manipulador de eventos de um componente filho. Considere botões: dependendo de onde você está usando um componenteButton, você pode querer executar uma função diferente—talvez uma reproduza um filme e outra faça upload de uma imagem.
Para fazer isso, passe uma prop que o componente recebe de seu pai como o manipulador de eventos, assim:
Aqui, o componenteToolbarrenderiza umPlayButtone umUploadButton:
PlayButtonpassahandlePlayClickcomo a proponClickpara oButtoninterno.UploadButtonpassa() => alert('Uploading!')como a proponClickpara oButtoninterno.
Finalmente, seu componenteButtonaceita uma prop chamadaonClick. Ele passa essa prop diretamente para o<button>nativo do navegador comonClick={onClick}. Isso diz ao React para chamar a função passada ao clicar.
Se você usa umsistema de design, é comum que componentes como botões contenham estilização, mas não especifiquem o comportamento. Em vez disso, componentes comoPlayButton e UploadButtonpassarão os manipuladores de eventos para baixo.
Nomeando props de manipuladores de eventos
Componentes nativos como<button> e <div>suportam apenasnomes de eventos do navegadorcomoonClick. No entanto, ao criar seus próprios componentes, você pode nomear as props de seus manipuladores de eventos da maneira que preferir.
Por convenção, as props de manipuladores de eventos devem começar comon, seguido por uma letra maiúscula.
Por exemplo, a proponClickdo componenteButtonpoderia ter sido chamada deonSmash:
Neste exemplo,<button onClick={onSmash}>mostra que o<button>do navegador (minúsculo) ainda precisa de uma prop chamadaonClick, mas o nome da prop recebida pelo seu componente personalizadoButtonfica a seu critério!
Quando seu componente suporta múltiplas interações, você pode nomear as props de manipuladores de eventos para conceitos específicos da aplicação. Por exemplo, este componenteToolbarrecebe os manipuladores de eventosonPlayMovie e onUploadImage:
Observe como o componenteAppnão precisa sabero queToolbarfará comonPlayMovieouonUploadImage. Esse é um detalhe de implementação daToolbar. Aqui, aToolbaros passa adiante como manipuladoresonClickpara seusButtons, mas poderia mais tarde também acioná-los por um atalho de teclado. Nomear props com base em interações específicas do aplicativo, comoonPlayMovie, oferece flexibilidade para mudar como elas são usadas posteriormente.
Observação
Certifique-se de usar as tags HTML apropriadas para seus manipuladores de eventos. Por exemplo, para lidar com cliques, use<button onClick={handleClick}>em vez de<div onClick={handleClick}>. Usar um<button>real do navegador permite comportamentos nativos do navegador, como navegação por teclado. Se você não gosta do estilo padrão do navegador para um botão e quer que ele se pareça mais com um link ou outro elemento de interface, pode conseguir isso com CSS.Saiba mais sobre como escrever marcação acessível.
Propagação de eventos
Os manipuladores de eventos também capturarão eventos de quaisquer filhos que seu componente possa ter. Dizemos que um evento “borbulha” ou “se propaga” para cima na árvore: ele começa onde o evento aconteceu e depois sobe pela árvore.
Esta<div>contém dois botões. Tanto a<div>quantocada botão têm seus próprios manipuladoresonClick. Quais manipuladores você acha que serão acionados ao clicar em um botão?
Se você clicar em qualquer um dos botões, seuonClickserá executado primeiro, seguido pelo<div>paionClick. Portanto, duas mensagens aparecerão. Se você clicar na própria barra de ferramentas, apenas o<div>paionClickserá executado.
Armadilha
Todos os eventos se propagam no React, excetoonScroll, que funciona apenas na tag JSX à qual você o anexa.
Interrompendo a propagação
Os manipuladores de eventos recebem umobjeto de eventocomo seu único argumento. Por convenção, ele geralmente é chamado dee, que significa "evento". Você pode usar este objeto para ler informações sobre o evento.
Esse objeto de evento também permite que você interrompa a propagação. Se você quiser impedir que um evento alcance componentes pai, precisa chamare.stopPropagation()como este componenteButton faz:
Quando você clica em um botão:
- O React chama o manipulador
onClickpassado para o<button>. - Esse manipulador, definido em
Button, faz o seguinte:- Chama
e.stopPropagation(), impedindo que o evento se propague mais. - Chama a função
onClick, que é uma prop passada do componenteToolbar.
- Chama
- Essa função, definida no componente
Toolbar, exibe o alerta próprio do botão. - Como a propagação foi interrompida, o manipulador
<div>paionClicknãoé executado.
Como resultado doe.stopPropagation(), clicar nos botões agora mostra apenas um único alerta (do<button>) em vez dos dois (do<button>e da barra de ferramentas pai<div>). Clicar em um botão não é a mesma coisa que clicar na barra de ferramentas ao redor, portanto, interromper a propagação faz sentido para esta interface.
Passar manipuladores como alternativa à propagação
Observe como este manipulador de clique executa uma linha de códigoe entãochama a proponClickpassada pelo pai:
Você também pode adicionar mais código a este manipulador antes de chamar o manipulador de eventoonClickpai. Este padrão fornece umaalternativaà propagação. Ele permite que o componente filho lide com o evento, enquanto também permite que o componente pai especifique algum comportamento adicional. Ao contrário da propagação, não é automático. Mas o benefício deste padrão é que você pode seguir claramente toda a cadeia de código que é executada como resultado de algum evento.
Se você depende da propagação e é difícil rastrear quais manipuladores são executados e por quê, tente esta abordagem.
Prevenir o comportamento padrão
Alguns eventos do navegador têm um comportamento padrão associado a eles. Por exemplo, um evento de envio de<form>, que ocorre quando um botão dentro dele é clicado, recarregará a página inteira por padrão:
Você pode chamare.preventDefault()no objeto de evento para impedir que isso aconteça:
Não confundae.stopPropagation() e e.preventDefault(). Ambos são úteis, mas não estão relacionados:
- e.stopPropagation()impede que os manipuladores de eventos anexados às tags acima sejam acionados.
- e.preventDefault()previne o comportamento padrão do navegador para os poucos eventos que o possuem.
Os manipuladores de eventos podem ter efeitos colaterais?
Absolutamente! Os manipuladores de eventos são o melhor lugar para efeitos colaterais.
Ao contrário das funções de renderização, os manipuladores de eventos não precisam serpuros, então é um ótimo lugar paraalteraralgo—por exemplo, alterar o valor de uma entrada em resposta à digitação, ou alterar uma lista em resposta a um pressionamento de botão. No entanto, para alterar alguma informação, primeiro você precisa de uma maneira de armazená-la. No React, isso é feito usandoestado, a memória de um componente.Você aprenderá tudo sobre isso na próxima página.
Recapitulação
- Você pode manipular eventos passando uma função como prop para um elemento como
<button>. - Os manipuladores de eventos devem ser passados,não chamados!
onClick={handleClick}, nãoonClick={handleClick()}. - Você pode definir uma função de manipulador de eventos separadamente ou inline.
- Os manipuladores de eventos são definidos dentro de um componente, então eles podem acessar props.
- Você pode declarar um manipulador de eventos em um pai e passá-lo como prop para um filho.
- Você pode definir suas próprias props de manipulador de eventos com nomes específicos da aplicação.
- Os eventos se propagam para cima. Chame
e.stopPropagation()no primeiro argumento para impedir isso. - Os eventos podem ter um comportamento padrão indesejado do navegador. Chame
e.preventDefault()para impedir isso. - Chamar explicitamente uma prop de manipulador de eventos a partir de um manipulador filho é uma boa alternativa à propagação.
Experimente alguns desafios
Challenge 1 of 2:Corrija um manipulador de eventos #
Clicar neste botão deveria alternar o fundo da página entre branco e preto. No entanto, nada acontece quando você clica nele. Corrija o problema. (Não se preocupe com a lógica dentro de handleClick—essa parte está correta.)
