React中,因为异步操作的关系,组件销毁后调用了setState(),报警告,怎么解决?

componetWillMount() { fetch(url).then((data) => { return data.json(); }).then((res) => { this.setState({ .... }) }); }我在componetWillMount中访问了接口返回数据后,调用了setState,访问的时候按了后退,导致还没收到响应就销毁了组件 ,但是fetch请求没被结束掉,之后 收到响应就调用了setState(),发出警告。请问这种情况该怎么处理?在unmount中结束fetch吗?但fetch怎么结束呢?官方文档好像没有api
关注者
34
被浏览
4578

8 个回答

正确的做法是不要在请求callback里setState,用不会被卸载的组件请求然后用props分发下来数据。

这也是为什么Redux或者Mobx流行的原因,只用React基本就要踩到这种坑,因为除了最顶层的组件,有几个组件是真的不会被卸载的呢?

如果实在没办法临时解决,只能加个this.isUnmount,在componentWillUnmount设置为true,然后在fetch callback里判断如果this.isUnmount不为true的时候再setState。

另外,Facebook以前有篇blog说过这个,以前有个isMounted方法。isMounted is an Antipattern - React Blog

这里面还有cancellable promise的方法,不建议使用。最好将promise当作不可变的,这样心智模型比较简单。

fetch现在还不能取消(相关讨论:Aborting a fetch: The Next Generation · Issue #447 · whatwg/fetch),如果你在component life cycle里面进行异步操作会遇到setState warning。


解决方案有几个:

  • 自己封装一个cancelable Promise,在unmount的时候cancel掉。
  • 对于通用数据抽到redux的store里用connect传props。
  • 使用rxjs对异步做subscribe,unmount的时候dispose掉。
  • 在异步setState之前做mount判断。
  • 如果你确认这个异步setState没有侵入性,也可以不理它。warning的目的在于让开发者确认自己的编码存在潜在的问题,在prod下是不报的。