Home > database >  React > Define a common useEffect to use across components
React > Define a common useEffect to use across components

Time:12-04

Innocent React question here.

I have a useEffect method that closes a modal on the escape keypress, that is duplicated a few times in my code, that looks like this:

const [shouldShowModal, setShouldShowModal] = useProfileModal();

useEffect(() => {
  const closeModalOnEscape = (e: KeyboardEvent | any): void => {
    if (e.key === "Escape") setShouldShowModal(false);
  };
  document.addEventListener("keydown", closeModalOnEscape);
  return () => {
    document.removeEventListener("keydown", closeModalOnEscape);
  };
}, [setShouldShowModal]);

Is there a way I can define the useEffect piece to use across multiple components?

CodePudding user response:

Just define a custom hook that takes in a setter

const useCloseModalOnEscape = (setShouldShowModal) => {
  useEffect(() => {
    const closeModalOnEscape = (e: KeyboardEvent | any): void => {
      if (e.key === "Escape") setShouldShowModal(false);
    };
    document.addEventListener("keydown", closeModalOnEscape);
    return () => {
      document.removeEventListener("keydown", closeModalOnEscape);
    };
  }, [setShouldShowModal]);
}

And then use it like this:

const [shouldShowModal, setShouldShowModal] = useProfileModal();

useCloseModalOnEscape(setShouldShowModal);

You can rename setShouldShowModal or useCloseModalOnEscape to be something more accurate to your other use cases if they're not all in the context of closing modals.


If every instance of useProfileModal will close on escape, then you should just include the useEffect (from inside of useCloseModalOnEscape) in useProfileModal.

CodePudding user response:

Since every use of useProfileModal uses the effect, just put the effect inside useProfileModal. That way, the code in every component only needs to be

const [shouldShowModal, setShouldShowModal] = useProfileModal();

and have, in useProfileModal:

const useProfileModal = () => {
  // ...
  useEffect(() => {
    const closeModalOnEscape = (e: KeyboardEvent | any): void => {
      if (e.key === "Escape") setShouldShowModal(false);
    };
    document.addEventListener("keydown", closeModalOnEscape);
    return () => {
      document.removeEventListener("keydown", closeModalOnEscape);
    };
  }, [setShouldShowModal]);
  // ...
  return [shouldShowModal, setShouldShowModal];

CodePudding user response:

Yes, the useEffect code can be defined as a separate function and then called from multiple components.

// Define a custom hook to handle the keydown event
function useCloseModalOnEscape(toggleModal) {
  useEffect(() => {
    const closeModalOnEscape = (e: KeyboardEvent | any): void => {
      if (e.key === "Escape") toggleModal({ shouldShowModal: false });
    };
    document.addEventListener("keydown", closeModalOnEscape);
    return () => {
      document.removeEventListener("keydown", closeModalOnEscape);
    };
  }, [toggleModal]);
}

// Define a component that uses the custom hook
function MyComponent() {
  const [{ shouldShowModal, profile }, toggleModal] = useProfileModal();

  // Call the custom hook to handle the keydown event
  useCloseModalOnEscape(toggleModal);

  // Other component code...
}

useCloseModalOnEscape function is a custom hook that takes the toggleModal function as an argument and handles the keydown event. The MyComponent component uses the useProfileModal hook to get the toggleModal function, and then calls the `useClose

  • Related