React Zombie Child 是指在 React 組件中的一個常見問題。當一個父組件被銷毀時,它的子組件可能仍然存在於記憶體中,這些子組件被稱為“僵屍子組件”。 這種情況通常發生在非同步操作中,例如在父組件中發起了一個非同步請求,而在請求完成之前,父組件被銷毀了。但是,由於非同步請求的回調函數仍然存 ...
React Zombie Child 是指在 React 組件中的一個常見問題。當一個父組件被銷毀時,它的子組件可能仍然存在於記憶體中,這些子組件被稱為“僵屍子組件”。
這種情況通常發生在非同步操作中,例如在父組件中發起了一個非同步請求,而在請求完成之前,父組件被銷毀了。但是,由於非同步請求的回調函數仍然存在於記憶體中,它們會繼續執行,嘗試更新已經被銷毀的父組件的狀態或引用已經不存在的 DOM 元素。
這種情況可能導致一些問題,例如記憶體泄漏、不一致的 UI 狀態或錯誤的數據更新。為了避免這種情況,我們可以在父組件銷毀時,手動取消非同步操作或在回調函數中判斷父組件是否仍然存在。
以下是一個示例代碼,展示瞭如何處理 React 僵屍子組件的問題:
import React, { useState, useEffect } from 'react';
const ParentComponent = () => {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
// 在回調函數中判斷父組件是否仍然存在
if (!isUnmounted) {
setData(data);
}
} catch (error) {
console.error(error);
}
};
let isUnmounted = false;
fetchData();
return () => {
// 在父組件銷毀時取消非同步操作
isUnmounted = true;
};
}, []);
return (
<div>
{data ? (
<ChildComponent data={data} />
) : (
<div>Loading...</div>
)}
</div>
);
};
const ChildComponent = ({ data }) => {
return <div>{data}</div>;
};
export default ParentComponent;
在上面的示例代碼中,我們使用了 useEffect 鉤子來處理非同步操作。在 useEffect 的回調函數中,我們創建了一個變數 isUnmounted 來判斷父組件是否已經被銷毀。在非同步操作的回調函數中,我們首先判斷了 isUnmounted 的值,只有當父組件仍然存在時,才更新父組件的狀態。
通過這種方式,我們可以避免 React 僵屍子組件的問題,確保在父組件被銷毀時,相關的非同步操作也被正確地取消。
參考資料:
- https://github.com/pmndrs/zustand#readingwriting-state-and-reacting-to-changes-outside-of-components
- https://github.com/pmndrs/zustand/issues/302