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粉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.