使用历史记录时出现内存泄漏消息。



当我在UseEffect函数中传递history.push时。

function Home(props) {
useEffect(() => {
const fetchData = async () => {
const response = await listingService.allListingDetails(data.listingId);
let tasksReceived = response.data.tasks;
let tasks = [...tasksReceived];
setTasks(tasks);
setListing(response.data);
if (tasks.length < 1) {
history.push({
pathname: "/firstpage",
state: {
listing: response.data,
},
});
return;
}
};
}, [changeState]);
}

index.js:1警告:无法对已卸载的组件执行React状态更新。这是一个非操作,但它表明应用程序中存在内存泄漏。若要修复此问题,请取消useEffect清理函数中的所有订阅和异步任务。在家(http://localhost:3001/static/js/main.chunk.js:11116:79)

如果我在评论下面的行,内存泄漏错误就不会再出现了。

if (tasks.length < 1) {
history.push({
pathname: "/firstpage",
state: {
listing: response.data,
},
});

我的猜测是react试图在重定向发生并且组件已经卸载后应用setTaskssetListing的状态更新,请记住,状态更新不是立即的,而是分批的。只有当您有任务时,才可以尝试通过设置状态来重新排序逻辑,因为在重定向时更新状态是没有意义的。

const fetchData = async () => {
const response = await listingService.allListingDetails(data.listingId);
let tasksReceived = response.data.tasks;
let tasks = [...tasksReceived];
if (tasks.length < 1) {
history.push({
pathname: "/firstpage",
state: {
listing: response.data,
},
});
} else {
setTasks(tasks);
setListing(response.data);
}
};

这可能是因为react在您尝试导航的同时执行状态更新(history.push(。尝试分离代码(一边是获取,另一边是状态更新…(并返回history.push(清理函数(。

function Home(props) {
useEffect(() => {
const fetchData = async () => {
try {
const response = await listingService.allListingDetails(data.listingId);
let tasksReceived = response.data
return tasksReceived;
} catch (e) {
console.error(e)
return null;
}
}
const data = fetchData().then((data) => data);
setTasks(data?.tasks || []);
setListing(data || {});

if (data?.tasks.length < 1) {
return () => history.push({
pathname: "/firstpage",
state: {
listing: response.data,
},
});
}
}, [changeState]);
}

这是组件卸载后更新状态时的常见错误。

这可能是由于并发,也可能是由于调用不必要的使用效果,这取决于[changeState]arg

为了实现可追溯性,您可以调试以放置以下控制台.log((


const renderCount = 0;
const useEffectCallCount = 0;
function Home(props) {
console.log(`Redering ${renderCount++}`);
useEffect(() => {
const fetchData = async () => {
useEffectCallCount++;
const callId = useEffectCallCount;
console.log(`useEfect initiated. CallID: ${callId}`);
const response = await listingService.allListingDetails(data.listingId);
let tasksReceived = response.data.tasks;
let tasks = [...tasksReceived];
console.log(`updating component state. CallID:  ${callId}`);
setTasks(tasks);
setListing(response.data);
if (tasks.length < 1) {
console.log(`Redirecting to first page. CallID:  ${callId}`);
history.push({
pathname: "/firstpage",
state: {
listing: response.data,
},
});
}
};
///probably missing from the example is calling the fetchDataItself. Fire and forget
fetchData();
/// we return clean-up function, but in this case, we want just to perform console.log
return () => { console.log("Component is dismounted"); }
}, [changeState]);
}

由于设置状态为async,它将最终位于回调队列的末尾,并等待其他同步任务完成。

如果发生重定向,它会尝试更新不再装载的组件的状态。

尝试使用下面的代码

function Home(props) {
useEffect(() => {
const fetchData = async () => {
const response = await listingService.allListingDetails(data.listingId);
let tasksReceived = response.data.tasks;
let tasks = [...tasksReceived];
if (tasks.length < 1) {
history.push({
pathname: "/firstpage",
state: {
listing: response.data,
},
});

// This return finished the function
return;
}

// Only set these state if the redirect didn't happen
setTasks(tasks);
setListing(response.data);
};
}, [changeState]);
}

最新更新