React Hook - 清理 useEffect
来源:https://wareboss.com/react-hook-clean-up-useeffect/
上一篇文章我们学习了 useEffect 中的异步操作及其正确用法(React Hook - useEffect 中的异步函数)。
今天我们将学习如何使用useEffect React Hook的清理功能。
当您从已卸载的组件更新状态时,React 将抛出以下错误:
“无法对已卸载的组件执行 React 状态更新。此操作不会产生任何效果,但表明您的应用程序存在内存泄漏。要解决此问题,请在componentWillUnmount方法中取消所有订阅和异步任务。”
useEffect(() => {
//Do all the job, for example, subscribe a websocket channel
return function(){
//Unsubscribe websocket channel
};
}, []);
阻止对已卸载的组件进行更新:
在这里您将学习如何预防这个问题
useEffect(() => {
let isCancelled = false;
const runAsync = async () => {
try {
if (!isCancelled) {
// do the job
}
} catch (e) {
if (!isCancelled) {
throw e;
}
}
};
runAsync();
return () => {
isCancelled = true;
};
}, [...]);
与 setInterval/setTimeout 一起使用:
这是中止setInterval/setTimeout的一个不错解决方案:
useEffect(() => {
const interval = setInterval(() => {
console.log('Five Seconds!');
}, 5000);
return () => clearInterval(interval);
}, []);
想象一下这样的使用场景:你打开了这个组件,然后又关闭了它。
如果不进行清理,setInterval 回调函数会继续运行。
与 Firestore 实时数据库配合使用:
这在使用Firestore 实时数据库时非常有用:
useEffect(() => {
//Subscribe: firebase channel
const cleanUp = firebase.firestore().collection('photos') .doc(id)
.onSnapshot( doc => {
setLoading(false);
setPhotos(doc)
}, err => { setError(err); }
);
return () => cleanUp(); //Unsubscribe
}, []);
如果您忘记清理您的 Firestore 订阅,您可能会收到不必要的请求。
与 fetch + AbortController 一起使用:
使用fetch/es6中的AbortController取消 fetch :
useEffect(() => {
const abortController = new AbortController();
const fetchData = async () => {
try {
const ret = await fetch("/companies", { signal: abortController.signal });
const data = await ret.json();
// ...
}
catch(error) {
if (abortController.signal.aborted) {
// cancelled
}
else
throw error;
};
};
fetchData();
return () => abortController.abort();
}, [companies]);
使用 axios 请求:
以下是如何使用 axios 取消请求。
useEffect(() => {
const source = axios.CancelToken.source();
const fetchData = async () => {
try {
const response = await Axios.get("/companies", {
cancelToken: source.token
});
// ...
} catch (error) {
if (Axios.isCancel(error)) {
//cancelled
} else {
throw error;
}
}
};
fetchData()
return () => {
source.cancel();
};
}, [companies]);
useEffect函数相当于React 类组件中的componentDidMount函数。
清理函数相当于React 类组件中的componentWillUnmount 函数。
下一篇文章:React 类组件和React 函数组件的区别。
再见!
文章来源:https://dev.to/iquirino/react-hook-clean-up-useeffect-24e7