首页  >  问答  >  正文

为什么当我使用 props 中的函数时会触发 useEffect (函数没有改变)?

主要组件正在调用模态/对话框。

[...]
  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)不会改变。

P粉662802882P粉662802882374 天前396

全部回复(1)我来回复

  • P粉165823783

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

    当依赖数组中的任何依赖项发生更改时,React 中的 useEffect 挂钩就会运行。在您的情况下,useEffect 依赖于onClose 属性。因此,每次 onClose 属性更改时都会运行。

    但是,即使代码中的 onClose 函数未发生更改,由于 JavaScript 处理函数标识的方式,useEffect 可能仍会运行。在 JavaScript 中,每次定义函数时,它都是一个新实例,即使它执行完全相同的操作。

    因此,就您而言,每次组件重新渲染时,您都将 closeDialog 定义为渲染函数中的新函数。这意味着,从 React 的角度来看,onClose 每次都是一个新函数,它会触发 useEffect

    要解决此问题,您可以使用 useCallback 挂钩来确保您的 closeDialog 函数在渲染之间具有稳定的标识,除非其依赖项发生变化:

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

    在上面的示例中,useCallback 返回函数的记忆版本,该版本仅在依赖项之一发生更改时才会更改。在这种情况下,依赖项数组为空 ([]),这意味着 closeDialog 函数的标识在重新渲染时将保持稳定。

    回复
    0
  • 取消回复