首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >React组件未在状态更改时重新呈现

React组件未在状态更改时重新呈现
EN

Stack Overflow用户
提问于 2014-09-19 23:25:40
回答 9查看 154.6K关注 0票数 58

我有一个React类,它将转到一个API来获取内容。我已经确认数据正在返回,但不会重新渲染:

代码语言:javascript
复制
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>
    );
  }
});

然而,如果我像下面这样添加一个debuggernewDeals就会被填充,然后一旦我继续,我就会看到数据:

代码语言:javascript
复制
  loadDealsFromServer: function() {
    var newDeals = [];

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

这是最新的交易列表:

代码语言:javascript
复制
var Gmail = React.createClass({
  render: function() {
    return (
      <div className="main">
        <div className="panel">
          <DealsList person={this.props.person} />
        </div>
      </div>
    );
  }
});
EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2014-09-19 23:45:10

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

代码语言:javascript
复制
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 });

当您使用调试器暂停脚本时,您为调用回调提供了扩展时间;当您继续时,数据已经到达并且看起来工作正常。

要修复此问题,您需要在数据从Chrome扩展返回之后执行setState调用:

代码语言:javascript
复制
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)

编辑

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

票数 26
EN

Stack Overflow用户

发布于 2015-10-04 03:43:16

我想在此添加一个非常简单,但很容易犯的错误:

代码语言:javascript
复制
this.state.something = 'changed';

..。然后不明白为什么它没有呈现,谷歌搜索和出现在这个页面上,只是意识到你应该写下:

代码语言:javascript
复制
this.setState({something: 'changed'});

React仅在使用setState更新状态时触发重新渲染。

票数 89
EN

Stack Overflow用户

发布于 2021-05-02 15:57:17

我的场景有点不同。我想很多像我这样的新手都会被难住--所以在这里分享。

我的状态变量是一个使用useState管理的JSON对象数组,如下所示:

代码语言:javascript
复制
const [toCompare, setToCompare] = useState([]);

但是,当使用下面的函数中的setToCompare更新toCompare时-重新渲染将不会触发。把它移到不同的组件上也不起作用。只有当其他事件触发re-render时,更新后的列表才会出现。

代码语言:javascript
复制
const addUniversityToCompare = async(chiptoadd) =>
  {
      var currentToCompare = toCompare;
      currentToCompare.push(chiptoadd);
      setToCompare(currentToCompare);
  }

这就是我的解决方案。基本上-赋值数组就是复制引用- react不会将其视为更改-因为对数组的引用并没有更改-只是其中的内容。因此,在下面的代码中-只是使用slice复制了数组-没有任何更改-并在mods之后将其分配回来。工作得很好。

代码语言:javascript
复制
const addUniversityToCompare = async (chiptoadd) => {
    var currentToCompare = toCompare.slice();
    currentToCompare.push(chiptoadd);
    setToCompare(currentToCompare);
}

希望这对像我这样的人有帮助。任何人,如果你觉得我错了,请让我知道--或者有其他方法。

提前谢谢。

票数 22
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25937369

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档