Main组件正在调用Modal/Dialog。
[...]
const closeDialog = () => setIsOpenDialog(false);
return (
<MyDialog
isOpen={isOpenDialog}
onClose={closeDialog}
/>
);
MyDialog代码是:
[...]
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>
);
}
当我单击Cancel并调用onClose
时,我可以看到useEffect
被触发。请问原因是什么?我的理解是不应该,因为onClose
函数对象(来自props
)没有改变。
3条答案
按热度按时间7gs2gvoe1#
React中的
useEffect
钩子会在依赖数组中的任何依赖发生变化时运行。在您的示例中,useEffect
依赖于onClose
属性。因此,它将在每次onClose
属性更改时运行。然而,即使
onClose
函数在代码中没有改变,useEffect
仍然可能由于JavaScript处理函数标识的方式而运行。在JavaScript中,每次你定义一个函数,它都是一个新的示例,即使它做的是完全相同的事情。因此,在本例中,每次组件重新渲染时,都将
closeDialog
定义为render函数中的新函数。这意味着,从React的Angular 来看,onClose
每次都是一个新函数,它会触发useEffect
。为了解决这个问题,你可以使用
useCallback
钩子来确保你的closeDialog
函数在渲染器上有一个稳定的标识,除非它的依赖关系发生了变化:在上面的例子中,
useCallback
返回一个记忆化的函数版本,只有当其中一个依赖项发生变化时,它才会发生变化。在本例中,dependencies数组为空([]),这意味着closeDialog
函数的标识在重新呈现时将是稳定的。c6ubokkw2#
MyDialog
组件中的useEffect
钩子被触发,因为指定了依赖数组**onClose
。这意味着只要onClose
的值发生变化,效果就会运行。虽然onClose
的函数引用在MyDialog
组件的整个生命周期中保持不变,但效果不是比较函数引用本身,而是比较每个渲染周期中onClose
的值。当调用onClose
函数时,MyDialog
组件会再次渲染,然后创建一个新的onClose
函数示例。这会导致onClose
的值发生变化,从而触发useEffect
**钩子。ql3eal8s3#
在JavaScript中,这个术语被称为引用相等。
示例:
因此,当react重新呈现组件时,它会重新声明这个函数
因此,如果useEffect将function1作为依赖项,则会将 Second Sender 中的声明与 First Render 中的声明进行比较。
所以它将导致
111 !== 112
然后根据这个条件它将重新运行useEffect。要解决此问题:
**函数:**可以使用
useCallback
钩子对于对象和数组可以使用
useMemo
钩子