Javascript React 组件不会在状态更改时重新渲染

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25937369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:06:46  来源:igfitidea点击:

React component not re-rendering on state change

javascriptreactjs

提问by brandonhilkert

I have a React Class that's going to an API to get content. I've confirmed the data is coming back, but it's not re-rendering:

我有一个 React 类,它将通过 API 获取内容。我已经确认数据回来了,但它没有重新渲染:

var DealsList = React.createClass({
  getInitialState: function() {
    return { deals: [] };
  },
  componentDidMount: function() {
    this.loadDealsFromServer();
  },
  loadDealsFromServer: function() {
    var newDeals = [];

    chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) {
      newDeals = deals;
    });

    this.setState({ deals: newDeals });
  },
  render: function() {
    var dealNodes = this.state.deals.map(function(deal, index) {
      return (
        <Deal deal={deal} key={index} />
      );
    });
    return (
      <div className="deals">
        <table>
          <thead>
            <tr>
              <td>Name</td>
              <td>Amount</td>
              <td>Stage</td>
              <td>Probability</td>
              <td>Status</td>
              <td>Exp. Close</td>
            </tr>
          </thead>
          <tbody>
            {dealNodes}
          </tbody>
        </table>
      </div>
    );
  }
});

However, if I add a debuggerlike below, newDealsare populated, and then once I continue, i see the data:

但是,如果我在debugger下面添加一个像,newDeals则填充,然后一旦我继续,我就会看到数据:

  loadDealsFromServer: function() {
    var newDeals = [];

    chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) {
      newDeals = deals;
    });
    debugger
    this.setState({ deals: newDeals });
  },

This is what's calling deals list:

这就是所谓的交易清单:

var Gmail = React.createClass({
  render: function() {
    return (
      <div className="main">
        <div className="panel">
          <DealsList person={this.props.person} />
        </div>
      </div>
    );
  }
});

采纳答案by Michelle Tilley

That's because the response from chrome.runtime.sendMessageis asynchronous; here's the order of operations:

那是因为来自的响应chrome.runtime.sendMessage是异步的;这是操作顺序:

var newDeals = [];

// (1) first chrome.runtime.sendMessage is called, and *registers a callback*
// so that when the data comes back *in the future*
// the function will be called
chrome.runtime.sendMessage({...}, function(deals) {
  // (3) sometime in the future, this function runs,
  // but it's too late
  newDeals = deals;
});

// (2) this is called immediately, `newDeals` is an empty array
this.setState({ deals: newDeals });

When you pause the script with the debugger, you're giving the extension time to call the callback; by the time you continue, the data has arrived and it appears to work.

当你用调试器暂停脚本时,你给了调用回调的扩展时间;当您继续时,数据已经到达并且似乎可以工作。

To fix, you want to do the setStatecall after the data comes back from the Chrome extension:

要修复,您希望setState在数据从 Chrome 扩展程序返回后进行调用:

var newDeals = [];

// (1) first chrome.runtime.sendMessage is called, and *registers a callback*
// so that when the data comes back *in the future*
// the function will be called
chrome.runtime.sendMessage({...}, function(deals) {
  // (2) sometime in the future, this function runs
  newDeals = deals;

  // (3) now you can call `setState` with the data
  this.setState({ deals: newDeals });
}.bind(this)); // Don't forget to bind(this) (or use an arrow function)

[Edit]

[编辑]

If this doesn't work for you, check out the other answers on this question, which explain other reasons your component might not be updating.

如果这对您不起作用,请查看此问题的其他答案,其中解释了您的组件可能无法更新的其他原因。

回答by Stijn de Witt

I'd like to add to this the enormously simple, but oh so easily made mistake of writing:

我想添加一个非常简单但很容易出错的写作错误:

this.state.something = 'changed';

... and then not understanding why it's not rendering and Googling and coming on this page, only to realize that you should have written:

...然后不明白为什么它不渲染和谷歌搜索并来到这个页面,才意识到你应该写:

this.setState({something: 'changed'});

React only triggers a re-render if you use setStateto update the state.

如果您用于setState更新状态,React 只会触发重新渲染。

回答by Lynn

Another oh-so-easy mistake, which was the source of the problem for me: I'd written my own shouldComponentUpdatemethod, which didn't check the new state change I'd added.

另一个非常简单的错误,这是我问题的根源:我编写了自己的shouldComponentUpdate方法,但没有检查我添加的新状态更改。

回答by derf26

In my case, I was calling this.setState({})correctly, but I my function wasn't bound to this, so it wasn't working. Adding .bind(this)to the function call or doing this.foo = this.foo.bind(this)in the constructor fixed it.

在我的情况下,我调用this.setState({})正确,但我的函数没有绑定到这个,所以它不起作用。添加.bind(this)到函数调用或this.foo = this.foo.bind(this)在构造函数中执行修复它。

回答by AndroConsis

I was going through same issue in React-Native where API response & reject weren't updating states

我在 React-Native 中遇到了同样的问题,其中 API 响应和拒绝没有更新状态

apiCall().then(function(resp) { this.setState({data: resp}) // wasn't updating }

apiCall().then(function(resp) { this.setState({data: resp}) // wasn't updating }

I solved the problem by changing functionwith the arrow function

我通过改变function箭头函数解决了这个问题

apiCall().then((resp) => {
    this.setState({data: resp}) // rendering the view as expected
}

For me, it was a binding issue. Using arrow functions solved it because arrow function doesn't create its's own this, its always bounded to its outer context where it comes from

对我来说,这是一个有约束力的问题。使用箭头函数解决了这个问题,因为箭头函数不会创建自己的this,它总是绑定到它来自的外部上下文