主要元件正在呼叫模態/對話框。
[...] 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粉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
函數的標識在重新渲染時將保持穩定。