在React開發中,我們可能經常會遇到這個一個警告:
我們不能在組件銷毀后設置state,防止出現內存泄漏的情況:
關於react中切換路由時報以上錯誤,實際的原因是因為在組件掛載(mounted)之后進行了異步操作,比如ajax請求或者設置了定時器等,而你在callback中進行了setState操作。當你切換路由時,組件已經被卸載(unmounted)了,此時異步操作中callback還在執行,因此setState沒有得到值。
解決的方式有兩種:
一、在卸載的時候對所有的操作進行清除(例如:abort你的ajax請求或者清除定時器)
componentDidMount = () => { //1.ajax請求 $.ajax('你的請求',{}) .then(res => { this.setState({ aa:true }) }) .catch(err => {}) //2.定時器 timer = setTimeout(() => { //dosomething },1000) } componentWillUnMount = () => { //1.ajax請求 $.ajax.abort() //2.定時器 clearTimeout(timer) }
二、設置一個flag,當unmount的時候重置這個flag
componentDidMount = () => { this._isMounted = true; $.ajax('你的請求',{}) .then(res => { if(this._isMounted){ this.setState({ aa:true }) } }) .catch(err => {}) } componentWillUnMount = () => { this._isMounted = false; }
三、最簡單的方式(萬金油)
componentDidMount = () => { $.ajax('你的請求',{}) .then(res => { this.setState({ data: datas, }); }) .catch(error => { }); } componentWillUnmount = () => { this.setState = (state,callback)=>{ return; }; }
四、在組件已經卸載時return,不去設置state:使用react組件this里面的updater屬性上的isMounted方法判斷組件是否存在,如果不存在,就return,不再去設置setState。
if (this.updater.isMounted(this)) { this.setState({ dashBoardDate: otherDashBoardDate }) } else { return }
五、react Hooks 解決:
useEffect(() => { let isUnmounted = false const abortController = new window.AbortController request.get('xxxxxx').then((resp:any):any => { if(resp.code == 200 && !isUnmounted){
this.setState({
//....
})
}
}).finally(() => { }) return () => { isUnmounted = true abortController.abort }; },[]);