无法在卸载的组件上调用setState(或forceUpdate)

时间:2018-05-19 19:39:23

标签: javascript reactjs react-lifecycle

我尝试在更新组件后从服务器获取数据,但我无法做到这一点。据我所知,当组件即将被销毁时调用componentWillUnmount,但我永远不需要销毁它,因此它对我没用。这会是什么解决方案?什么时候我应该设置状态?

async componentDidUpdate(prevProps, prevState) {
  if (this.props.subject.length && prevProps.subject !== this.props.subject) {
    let result = await this.getGrades({
      student: this.props.id,
      subject: this.props.subject
    });
    this.setState({
      subject: this.props.subject,
      grades: result
    });
  }
}

async getGrades(params) {
  let response, body;

  if (params['subject'].length) {
    response = await fetch(apiRequestString.gradesBySubject(params));
    body = await response.json();
  } else {
    response = await fetch(apiRequestString.grades(params));
    body = await response.json();
  }

  if (response.status !== 200) throw Error(body.message);

  return body;
}

完整错误:

Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, 
but it indicates a memory leak in your application. To fix, cancel all subscriptions and
asynchronous tasks in the componentWillUnmount method.

2 个答案:

答案 0 :(得分:42)

我在这个例子中使用的常见模式是

componentWillUnmount() {
    this.isCancelled = true;
}

然后在您正在等待解析异步函数的代码中,您需要在设置状态之前添加一个检查:

async componentDidUpdate(prevProps, prevState) {
    if (this.props.subject.length && prevProps.subject !== this.props.subject) {
        let result = await this.getGrades({
            student: this.props.id,
            subject: this.props.subject
        });
        !this.isCancelled && this.setState({
            subject: this.props.subject,
            grades: result
        });
    }
}

这将停止卸载/卸载组件的任何状态设置

答案 1 :(得分:1)

可接受的答案有效,并且是在组件呈现方法(getInitialState,componentWillMount,componentDidMount)中调用异步函数的问题的有效解决方法。

但是更好的做法是使用状态管理助手(例如Redux和Flux)以及全局存储,这可以避免多个setState的问题。