React - 在未安装的组件上的setState() [英] React - setState() on unmounted component

查看:168
本文介绍了React - 在未安装的组件上的setState()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的react组件中,我试图在ajax请求正在进行时实现一个简单的微调器 - 我使用state来存储加载状态。

In my react component im trying to implement a simple spinner while an ajax request is in progress - im using state to store the loading status.

出于某种原因,我的React组件中的这段代码会抛出此错误

For some reason this piece of code below in my React component throws this error


只能更新已安装或安装的组件。这通常意味着您在已卸载的组件上调用了set $()
。这是一个无操作。
请检查未定义组件的代码。

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 undefined component.

如果我摆脱了第一个setState调用,则错误消失。

If I get rid of the first setState call the error goes away.

constructor(props) {
  super(props);
  this.loadSearches = this.loadSearches.bind(this);

  this.state = {
    loading: false
  }
}

loadSearches() {

  this.setState({
    loading: true,
    searches: []
  });

  console.log('Loading Searches..');

  $.ajax({
    url: this.props.source + '?projectId=' + this.props.projectId,
    dataType: 'json',
    crossDomain: true,
    success: function(data) {
      this.setState({
        loading: false
      });
    }.bind(this),
    error: function(xhr, status, err) {
      console.error(this.props.url, status, err.toString());
      this.setState({
        loading: false
      });
    }.bind(this)
  });
}

componentDidMount() {
  setInterval(this.loadSearches, this.props.pollInterval);
}

render() {

    let searches = this.state.searches || [];


    return (<div>
          <Table striped bordered condensed hover>
          <thead>
            <tr>
              <th>Name</th>
              <th>Submit Date</th>
              <th>Dataset &amp; Datatype</th>
              <th>Results</th>
              <th>Last Downloaded</th>
            </tr>
          </thead>
          {
          searches.map(function(search) {

                let createdDate = moment(search.createdDate, 'X').format("YYYY-MM-DD");
                let downloadedDate = moment(search.downloadedDate, 'X').format("YYYY-MM-DD");
                let records = 0;
                let status = search.status ? search.status.toLowerCase() : ''

                return (
                <tbody key={search.id}>
                  <tr>
                    <td>{search.name}</td>
                    <td>{createdDate}</td>
                    <td>{search.dataset}</td>
                    <td>{records}</td>
                    <td>{downloadedDate}</td>
                  </tr>
                </tbody>
              );
          }
          </Table >
          </div>
      );
  }

问题是为什么我在组件时遇到此错误应该已经挂载(因为它是从componentDidMount调用的)我认为安装组件后设置状态是安全的吗?

The question is why am I getting this error when the component should already be mounted (as its being called from componentDidMount) I thought it was safe to set state once the component is mounted ?

推荐答案

没有看到渲染功能有点困难。虽然已经可以发现你应该做的事情,但每次你使用一个间隔时你必须在卸载时清除它。所以:

Without seeing the render function is a bit tough. Although can already spot something you should do, every time you use an interval you got to clear it on unmount. So:

componentDidMount() {
    this.loadInterval = setInterval(this.loadSearches, this.props.pollInterval);
}

componentWillUnmount () {
    this.loadInterval && clearInterval(this.loadInterval);
    this.loadInterval = false;
}

由于在卸载后仍可能会调用这些成功和错误回调,因此您可以使用用于检查它是否已挂载的区间变量。

Since those success and error callbacks might still get called after unmount, you can use the interval variable to check if it's mounted.

this.loadInterval && this.setState({
    loading: false
});

希望这会有所帮助,如果这不起作用,则提供渲染功能。

Hope this helps, provide the render function if this doesn't do the job.

干杯

这篇关于React - 在未安装的组件上的setState()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆