首頁  >  問答  >  主體

為什麼當我使用 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 天前395

全部回覆(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
  • 取消回覆