Reactjs 如何在useffect中阻止内存泄漏
我使用effecthook从服务器获取数据,这些数据被传递到react表,在那里我使用相同的api调用从服务器加载下一组数据。 当应用程序加载时,我会收到如下警告Reactjs 如何在useffect中阻止内存泄漏,reactjs,react-table,use-effect,Reactjs,React Table,Use Effect,我使用effecthook从服务器获取数据,这些数据被传递到react表,在那里我使用相同的api调用从服务器加载下一组数据。 当应用程序加载时,我会收到如下警告 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscript
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
效果挂钩:
useEffect(() => {
setPageLoading(true);
props
.dispatch(fetchCourses())
.then(() => {
setPageLoading(false);
})
.catch((error: string) => {
toast.error(error);
setPageLoading(false);
});
}, []);
反应表页面:
<ReactTable
className="-striped -highlight"
columns={columns}
data={coursesData}
defaultPage={currentPage}
defaultPageSize={courses.perPage}
loading={isLoading}
manual={true}
onFetchData={setFilter}
/>
是否有人知道如何使用react和useEffect清理钩子?您可以返回一个将在清理时运行的函数。所以在你的情况下,你会想要这样的东西:
useEffect(() => {
let unmounted = false;
setPageLoading(true);
props
.dispatch(fetchCourses())
.then(() => {
if (!unmounted) {
setPageLoading(false);
}
})
.catch((error: string) => {
if (!unmounted) {
toast.error(error);
setPageLoading(false);
}
});
return () => { unmounted = true };
}, []);
编辑:如果您需要在useEffect之外启动调用,那么它仍然需要检查未安装的变量,以确定是否应该跳过对setState的调用。这个未安装的变量将由useEffect设置,但是现在您需要克服一些障碍,以使变量可以在效果之外访问
const Example = (props) => {
const unmounted = useRef(false);
useEffect(() => {
return () => { unmounted.current = true }
}, []);
const setFilter = () => {
// ...
props.dispatch(fetchCourses()).then(() => {
if (!unmounted.current) {
setLoading(false);
}
})
}
// ...
return (
<ReactTable onFetchData={setFilter} /* other props omitted */ />
);
}
const示例=(道具)=>{
const unmounted=useRef(false);
useffect(()=>{
return()=>{unmounted.current=true}
}, []);
常量setFilter=()=>{
// ...
props.dispatch(fetchCourses())。然后(()=>{
如果(!unmounted.current){
设置加载(假);
}
})
}
// ...
返回(
);
}
其他答案当然有效,我只是想分享我想出的一个解决方案。
我构建了一个类似React的useState的功能,但是只有在安装组件时才会设置state。我发现它更优雅,因为您不必在组件中乱用isMounted变量
安装:
用法:
const[count,setCount]=useStateIfMounted(0);
您可以在钩子的上找到更高级的文档。但是如果在没有useEffect的情况下再次执行相同的API调用该怎么办。例如,如果API调用是useEffect,并且在函数中再次执行。@Nicholas Tower如果您看到setFilter函数,则会调用相同的调度调用fetchCourses()。如果两个调用同时发生,我将收到内存泄漏警告。如果我在setFilter函数中隐藏调用,那么就没有内存泄漏警告。该repo的作者说这不是一个可行的解决方案(只是隐藏了警告消息)。我也很沮丧,但只是想告诉大家。
const Example = (props) => {
const unmounted = useRef(false);
useEffect(() => {
return () => { unmounted.current = true }
}, []);
const setFilter = () => {
// ...
props.dispatch(fetchCourses()).then(() => {
if (!unmounted.current) {
setLoading(false);
}
})
}
// ...
return (
<ReactTable onFetchData={setFilter} /* other props omitted */ />
);
}
npm install use-state-if-mounted