Modal funcional com React Hooks
Meu objetivo é mostrar um pouco do comportamento de um componente funcional React.
Iremos criar um componente de modal apenas usando React hooks. Nosso modal deverá ter o seguinte comportamento:
HOOKS
Juntamente com componentes funcionais precisamos utilizar os hooks. Essa feature é que vai permitir nossos componentes de função ter as mesmas características de um componente de classe: utilizar estado, executar ação ao montar um componente, entre outras coisas mais.
O uso de componentes funcionais surgiu em 2018 para substituir os componentes de classe. São mais simples de escrever (menos verbosos) e ainda mais performáticos.
Recomendo buscar mais detalhes dos hooks. Não falarei muito sobre isso pois não é o objetivo aqui.
Abaixo link para API de referência Hook:
Vamos para o código!
Começaremos usando o comando
npx create-react-app modal-react
em uma pasta a sua escolha (modal-react será o nome da aplicação). Esse comando pode levar algum tempinho e irá construir uma aplicação básica com uso do React.
Criando o Componente
O comando irá gerar um App.js. Vamos refatorar para o ECMAScript 6:
O componente Modal mostrado acima corresponde ao nosso modal, crie a pasta src/Component/Modal e lá crie o arquivo Modal.jsx:
O props serve para recuperar os parâmetros que o componente pode receber ao ser declarado.
Também adicione na mesma pasta o arquivo Modal.css:
useState
O useState retorna uma variável e uma função assíncrona que serve para alterar o valor dessa variável. Nosso parâmetro indica o valor inicial dessa variável.
O setDropdown após receber um novo valor o coloca na fila de re-renderização do componente.
Repare que colocamos a função de showDropdown no click do botão e adicionamos um evento ao body. Quando clicarmos no botão, o modal deve aparecer, mas quando clicarmos em qualquer outro canto (no body) ele deve sumir. A variável dropdown (que estamos alterando o valor) é passada via props para o Modal e isso adicionará comportamento css ao nosso componente.
Adicione o seguinte trecho ao App.css para o comportamento explicado acima funcionar:
Até aqui temos dois problemas: quando clicamos dentro do modal ele irá desaparecer e quando clicamos no botão pela segunda vez o Modal não irá sair da tela…Não é isso que queremos, cuidaremos disso mais adiante.
Propagação de evento
Como podemos evitar que o modal desapareça e apareça logo em seguida quando o botão é clicado?
O que acontece aí é causado pelo efeito de capturing (que podemos ver na imagem). O evento do click começa lá na raíz e se propaga até chegar no botão. Ou seja, executa nossas duas funções sempre que o botão é clicado, já que o body é ancestral do botão.
A função .stopPropagation() vai impedir que o click chegue até a ação do botão, parando no body (como mostrarei o código a seguir juntamente com o useRef).
Para mais detalhes recomendo o link abaixo:
useRef
Esse outro hook nos retorna um objeto no qual podemos inicializar passando parâmetro. Teremos acesso a esse objeto pela propriedade .current. O objeto retornado aqui persistirá durante todo ciclo de vida do componente.
Atente-se a props modalRef que é passada no componente Modal. É a referência dele que vamos pegar com .current e então podemos verificar se o evento de click contém ou não o nosso Modal.
Chegando até aqui o seu modal já deve estar funcionando perfeitamente! :)
Código completo
O código apresentado está em repositório público no meu Github: