今天我们将看到如何使用useEffect React Hook的清理函数。
当你更新卸载组件的状态时,React会抛出这样的错误:
"无法在卸载的组件上执行React状态更新。这是一个无操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消componentWillUnmount方法中的所有订阅和异步任务。”**
useEffect(() => {
//Do all the job, for example, subscribe a websocket channel
return function(){
//Unsubscribe websocket channel
};
}, []);
----1防止更新卸载组件:
在这里你将学习如何防止这个问题
useEffect(() => {
let isCancelled = false;
const runAsync = async () => {
try {
if (!isCancelled) {
// do the job
}
} catch (e) {
if (!isCancelled) {
throw e;
}
}
};
runAsync();
return () => {
isCancelled = true;
};
}, [...]);
Usage with setInterval/setTimeout:
This is a nice solution to abort setInterval/setTimeout:
2使用与setInterval / setTimeout:
这是中止setInterval/setTimeout的一个很好的解决方案:
useEffect(() => {
const interval = setInterval(() => {
console.log('Five Seconds!');
}, 5000);
return () => clearInterval(interval);
}, []);
----3使用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订阅,您可能会收到不必要的请求。
4Usage with fetch + AbortController:
Cancel fecth with AbortController from fetch/es6:、
使用fetch + AbortController:
用AbortController从fetch/es6取消fecth:
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]);
–5Usage with axios request:
Here is how to cancel the request with 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函数。