search

Home  >  Q&A  >  body text

Why does useEffect fire when I use a function from props (the function didn't change)?

The main component is calling the modal/dialog.

[...]
  const closeDialog = () => setIsOpenDialog(false);
  return (
      <MyDialog
        isOpen={isOpenDialog}
        onClose={closeDialog}
      />
  );

MyDialog code is:

[...]
  useEffect(() => {
    console.log('This removes dialog states (data)!')
  }, [onClose]);

export default function MyDialog({
  isOpen,
  onClose,
}) {
    return (
    <Dialog
      isOpen={isOpen}
      onClose={onClose}
      dialogTitle="Add/Edit"
      onClickCancel={onClose}
    >
    [...]
    </Dialog>
);
}

When I click Cancel and call onClose, I can see that useEffect has triggered. may I know what is the reason? My understanding is that it shouldn't, because the onClose function object (from props) does not change.

P粉662802882P粉662802882440 days ago450

reply all(1)I'll reply

  • P粉165823783

    P粉1658237832023-09-13 11:52:56

    The useEffect hook in React runs when any dependency in the dependency array changes. In your case, useEffect relies on the onClose property. Therefore, it will be run every time the onClose property changes.

    However, even if the onClose function does not change in the code, useEffect may still run due to the way JavaScript handles function identification. In JavaScript, every time you define a function, it's a new instance, even if it does the exact same thing.

    So in your case, every time the component re-renders, you define closeDialog as a new function in the render function. This means that, from React's perspective, onClose is a new function each time that triggers useEffect.

    To solve this problem, you can use the useCallback hook to ensure that your closeDialog function has a stable identity between renders unless its dependencies change:

    const closeDialog = React.useCallback(() => setIsOpenDialog(false), []);

    In the example above, useCallback returns a memoized version of the function that only changes when one of its dependencies changes. In this case, the dependencies array is empty ([]), which means that the identity of the closeDialog function will remain stable across re-renders.

    reply
    0
  • Cancelreply