DEV Community

Cover image for React na Prática: Lidando com Eventos
Alvaro Guimarães
Alvaro Guimarães

Posted on

2 2 1 1 1

React na Prática: Lidando com Eventos

Lidando com Eventos

Outro caso comum, e que você já deve ter visto muitas vezes, é a lógica de lidar com eventos dentro do próprio componente.

Apesar do código estar simples, a responsabilidade do código pode ser divida em partes.

O código de escutar o escape pode ser extraído, pois também seria útil para menus, selects, ou qualquer outro componente que precise ouvir eventos de teclado.

import { useEffect, useState } from "react";

export function Modal({ isOpen, onChangeIsOpen }) {
  useEffect(() => {
    function handleClick(event: KeyboardEvent) {
      if (event.key === "Escape") {
        onChangeIsOpen(false);
      }
    }

    window.addEventListener("keydown", handleClick);

    return () => {
      window.removeEventListener("keydown", handleClick);
    };
  }, []);

  return (
    <div>
      <dialog open={isOpen}>
        <p>Greetings, one and all!</p>
        <button onClick={() => onChangeIsOpen(false)}>OK</button>
      </dialog>
      <button onClick={() => onChangeIsOpen(true)}>Abrir Modal</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Extraindo a lógica de escutar o teclado em um hook

No hook, a ideia é que você possa passar o código da tecla e a função de
callback, e o hook vai lidar com a lógica de escutar e remover o evento de teclado.

// useKeyPress.tsx
import { useEffect } from "react";

type useKeyPressParams = {
  keyCode: string;
  callback: (event: KeyboardEvent) => void;
};

export function useKeyPress({ keyCode, callback }: useKeyPressParams) {
  useEffect(() => {
    function handleClick(event: KeyboardEvent) {
      if (event.key === keyCode) {
        callback(event);
      }
    }

    window.addEventListener("keydown", handleClick);

    return () => {
      window.removeEventListener("keydown", handleClick);
    };
  }, [keyCode, callback]);
}
Enter fullscreen mode Exit fullscreen mode

Assim, o modal tem menos responsabilidades e o hook pode ser reutilizado em outros componentes.

// Modal.tsx
import { useCallback, useState } from "react";
import { useKeyPress } from "../hooks/useKeyPress";

export function Modal({isOpen, onChangeIsOpen}) {
  useKeyPress({ keyCode: "Escape", callback: onChangeIsOpen });

  return (
    <div>
      <dialog open={isOpen}>
        <p>Greetings, one and all!</p>
        <button onClick={() => onChangeIsOpen(false)}>OK</button>
      </dialog>
      <button onClick={() => onChangeIsOpen(true)}>Abrir Modal</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Isolando a lógica de abrir e fechar o modal em um hook

No exemplo acima, estamos delegando ao componente PAI para lidar com o estado do modal,
ainda, sim, dentro do próprio pai um estado deve ser criado e gerenciado.

É possível também encapsular a lógica de abrir e fechar o modal em um hook customizado,
assim o componente que usa o modal não precisa lidar com o estado do modal.

O código não está mais ou menos complexo, mas a responsabilidade de manter o estado
aberto ou fechado do modal foi delegada para o próprio hook.

// hooks/useModal.tsx
import { PropsWithChildren, useCallback, useState } from "react";

export function useModal() {
  const [isOpen, setIsOpen] = useState(false);

  const closeModal = useCallback(() => {
    setIsOpen(false);
  }, []);

  const openModal = useCallback(() => {
    setIsOpen(true);
  }, []);

  const Modal = useCallback(
    ({ children }: PropsWithChildren) => (
      <dialog open={isOpen}>{children}</dialog>
    ),
    [isOpen],
  );

  return {
    openModal,
    closeModal,
    Modal,
  };
}
Enter fullscreen mode Exit fullscreen mode
// App.tsx
import { useModal } from "./hooks/useModal";

function App() {
  const { Modal, openModal, closeModal } = useModal();

  return (
    <div>
      <Modal>
        <p>Greetings, one and all!</p>
        <button onClick={closeModal}>OK</button>
      </Modal>

      <button onClick={openModal}></button>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay