react,异步setState警告如何解决?

所有组件都会有ajax请求,现在切换的时候就会报错,
查了下要卸载的时候取消请求,我现在都快搞完,1百个api,不得写100遍?

阅读 2.9k
4 个回答

封装一个可以取消的api class
1.把所有的请求根据http方法封装一次(get,post,put,delete)
2.

class ApiWithCancel {
  get = (url, params) => {
    //get为自己封装的方法, 一下的post, put, del同理
    return this.makeCancelAble(get(url, params));
  }
  post = (url, params) => {
    return this.makeCancelAble(post(url, params));
  }
  put = (url, params) => {
    return this.makeCancelAble(put(url, params));
  }
  delete = (url, params) => {
    return this.makeCancelAble(fectchDel(url, params));
  }
  makeCancelAble = (promise) => {
    return new Promise(( resolve ) =>
      promise.then(val => !this.hasCanceled && resolve(val))
    );
  }
  cancel = () => {
    this.hasCanceled = true;
  }
}

3.在用到的组件里的constructor里,new一个这个class实例

this.api = new ApiWithCancel();

4.用的时候

const res = await this.api.get(url,params);

5.在组件卸载的时候取消

this.api.cancel()

注:代码可能不能直接用,因为里面有封装的,但是意思是这个意思,封装成一个class,每次new一下就可以了。另外数据放在redux里也可以避免这种报警,但是这前提是你的这些数据或者动作是应该放在redux里的。

没有用到redux-thunk 或者redux-saga之类的中间件?
组件中调用ajax一般只有componentDidmount()中触发,但也是交给redux来处理的。

出现你这种情况是你肯定在纯函数中调用了ajax,这是拒绝的。

这个react官方已经做了很详细的讨论了。 直接给你个代码吧。

如果想知道来龙去脉, 戳这里 https://reactjs.org/blog/2015...

const makeCancelable = (promise) => {
  let hasCanceled_ = false;

  const wrappedPromise = new Promise((resolve, reject) => {
    promise.then(
      val => hasCanceled_ ? reject({isCanceled: true}) : resolve(val),
      error => hasCanceled_ ? reject({isCanceled: true}) : reject(error)
    );
  });

  return {
    promise: wrappedPromise,
    cancel() {
      hasCanceled_ = true;
    },
  };
};

st cancelablePromise = makeCancelable(
  new Promise(r => component.setState({...}))
);

cancelablePromise
  .promise
  .then(() => console.log('resolved'))
  .catch((reason) => console.log('isCanceled', reason.isCanceled));

cancelablePromise.cancel(); // Cancel the promise

首先这个问题是ajax异步回调setState造成的,在切换组件的情况下出现,此时组件已经销毁了,再去调用setState就会警告.

上面几种方法都是有效的...
但是我目前项目并没有全部使用redux来处理异步,因为项目情况基本是一个api就单个组件会用到..

我的解决方法是路由变化的时候,取消上次一次全部未结束的请求,因为问题是ajax异步回调造成的,取消请求就不会走回调了!
这样就不用引入redux中间件处理异步,也不用挨个组件去判断是否卸载

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题