react-router路由快速切换时setState触发warning

#1

业务类型是:
每个路由进入的时候,componentDidMount时,都会去ajax异步调用接口,接收到数据的时候进行setState操作。

但是当我快速切换路由的时候,因为之前的component已经销毁了,但是ajax还进行中,返回时setState了已经销毁的component。会报错如下错误

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the MyDepartmentTrace component.

想到的解决方案
1、取消ajax请求,abort掉。但是如果多个ajax,fetch之类的不是要维护好多,每次请求都要存一下?或者怎么组织这些请求
2、success回调中判断component还是否存在,这个this. isMounted()貌似也不推荐用了,也得自己维护一套组件是否已经销毁了的代码,在mount和unmount中写入。然后setState的时候先检测下有没有被销毁了,感觉这个也麻烦
这种场景,一般都是如何避免的?

#2

切换好像没有遇到过这种错误提示

#3

所以,需要再切换的时候来统一管理异步请求,我用的是axios,我的解决方案是包装axios的get,post方法,做到了全局存放请求索引。在当前页面销毁的时候来执行取消所有的请求的全局方法,但是这么干每个页面都需要执行以下销毁方法。就算写在router 的onEnter 或者onLeave中也一样每个组件都需要写。那么问题来了。react有没有像vue那样的全局钩子函数啊。。实在找不到

#4

肯定有的啊,你当刚进入一个路由,然后直接单击其他路由,快速切换。如果异步请求没有立即返回,过了5秒钟返回了。会在新路由中,setState老的路由的数据,因为老的组件已经销毁了嘛,肯定会报错啊。

#5

谢谢回答!
对的,找不到。貌似只能用你说的:每个页面都需要执行一下销毁方法了。。。。

#6

测试了下发现还真是这样,这样的话你就把页面间切换会触发的ajax请求写到redux里吧,再次触发同种ajax时,取消上次的请求

#7

嗯,谢谢!
总的思路都是要保留一下之前请求的引用,需要的地方销毁请求。

#8

解决方法有两个

将constructor 中的方法放到componentDidMount 中去执行(不影响你的逻辑的前提下);
更优雅的解决方案就是使用redux-thunk去执行异步逻辑并将结果写入store,这样如果节点被unmount了也就不会收到通知了。

#9

异步返回的数据存入redux就好了

#10

好的,谢谢。redux的方案可以
不过第一个方案:将constructor 中的方法放到componentDidMount 中去执行(不影响你的逻辑的前提下); 我就是在didMount中执行ajax的啊,应该还是会有问题的吧。

#11

嗯,谢谢。

#12

将constructor 中的方法放到componentDidMount 一样还是会warning

#13

不客气!!!

没事可以看下这个链接

#14

作为程序员,管什么warning???

#15

呵呵

#16

我服