javascript 修改数据后,setState 不会触发重新渲染

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29459500/
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-10-28 10:34:06  来源:igfitidea点击:

setState not triggering a re-render when data has been modified

javascriptjsonreactjssetstate

提问by Joel

Just started working with React, and it's been going relatively smooth up until this point.

刚刚开始使用 React,到目前为止它一直相对顺利。

I have a list, that contains X pre-defined items, which means that the list is always rendered with a given amount of rows.

我有一个列表,其中包含 X 个预定义的项目,这意味着该列表始终以给定的行数呈现。

This data is collected from a REST API, prior to the list rendering. The data contains variables relating to the list, as well as an array that contains each item within the list.

此数据是在列表呈现之前从 REST API 收集的。数据包含与列表相关的变量,以及包含列表中每个项目的数组。

I chose the easy route, so I populate every component with a single JSON object named 'data', that contains everything necessary.

我选择了简单的路线,所以我用一个名为“data”的 JSON 对象填充每个组件,其中包含所有必需的内容。

Rendering the list looks something like this:

呈现列表看起来像这样:

<MyList data={data} />

Then, in the getInitialState of MyList:

然后,在 MyList 的 getInitialState 中:

dataInt: this.props.data.dataInt || 0,
dataStr: this.props.data.dataStr || '',
rows: this.props.data.rows || []

So I store my array of items (JSON) in the initial state of the list (parent), and when I choose to render the list, I first create all components (children) in an array, like this:

因此,我将我的项目数组 (JSON) 存储在列表的初始状态(父级)中,当我选择呈现列表时,我首先在数组中创建所有组件(子级),如下所示:

var toRender = [];
for(i = 0; i < this.state.rows.length; i++) {
    toRender.push(<ItemRow data={this.state.rows[i]} />);
}

and then I render like this:

然后我像这样渲染:

return (
    <div className="item-container">
        <table className="item-table">
            {toRender}
        </table>
    </div>
);

The render-function of MyItem look something like this:

MyItem 的渲染功能如下所示:

return (
    <tr>
        <td>{this.state.dataFromItem}</td>
    </tr>
);

Now, let's say I want to modify the child data from within the parent, with some new data I just got from the API. Same structure, just the value of one field/column has changed:

现在,假设我想使用刚从 API 获得的一些新数据,从父级内部修改子数据。相同的结构,只是一个字段/列的值发生了变化:

i = indexOfItemToBeUpdated;
var newRows = this.state.rows;
newRows[i] = data; // New JSON object with same keys, different values.
this.setState({ rows: newRows }); // Doesn't trigger re-render
this.forceUpdate(); // Doesn't trigger re-render

What am I doing wrong?

我究竟做错了什么?

At first I thought it was because I was wrapping the render function of MyItem in a , but since it renders perfectly fine on the initial render, I will assume that is an acceptable wrapper.

起初我认为这是因为我将 MyItem 的渲染函数包装在 a 中,但由于它在初始渲染时渲染得非常好,我将假设这是一个可接受的包装器。

After some testing, it seems that the parent view is re-rendered, but not the children (which are based on the data that is updated within the parent).

经过一些测试,似乎重新渲染了父视图,而不是子视图(基于父视图中更新的数据)。

JSfiddle: https://jsfiddle.net/zfenub6f/1/

JSfiddle:https://jsfiddle.net/zfenub6f/1/

回答by Derek

I think the problem could be the your are only using getInitialStatefor the Row. You are setting state with the passed in props. If the children get new props, getInitialStatewon't get called again. I always refer back to https://facebook.github.io/react/docs/component-specs.htmlto see all the lifecyle events. Try using componentWillReceiveProps(object nextProps)to set the state again. If you don't actually need statein the child, remove the use of state and just use propsand it probably will work.

我认为问题可能是您仅getInitialState用于Row. 您正在使用传入的道具设置状态。如果孩子们得到新道具,getInitialState就不会再被召唤了。我总是参考https://facebook.github.io/react/docs/component-specs.html来查看所有生命周期事件。componentWillReceiveProps(object nextProps)再次尝试使用设置状态。如果您实际上不需要state在孩子中使用,请删除 state 的使用,然后使用props它可能会起作用。

回答by Chris Hawkes

If you're children are using State and state is not updating, what about props? does that render just fine? If the parent changes the state of the children and the children don't reflect that change those child components most likely need a unique key assigned to them which tells React that these items need to be updated when the state is updated on the parent. I ran into a similar issue where props inside the child updated to reflect the parent but the state of the child would not update. Once I added keys, the solution was resolved. For further reading on this check out this blog that initially hinted the problem to me.

如果你的孩子们正在使用 State 而 state 没有更新,那么 props 呢?渲染得很好吗?如果父组件更改了子组件的状态,而子组件没有反映该更改,则这些子组件很可能需要为它们分配一个唯一键,这告诉 React 当父组件的状态更新时需要更新这些项目。我遇到了一个类似的问题,其中孩子内部的道具更新以反映父母,但孩子的状态不会更新。一旦我添加了密钥,解决方案就解决了。要进一步阅读此内容,请查看最初向我暗示问题的博客。

http://blog.arkency.com/2014/10/react-dot-js-and-dynamic-children-why-the-keys-are-important/

http://blog.arkency.com/2014/10/react-dot-js-and-dynamic-children-why-the-keys-are-important/

There is also the official documentation from React that explains this situation.

React 的官方文档也解释了这种情况。

http://facebook.github.io/react/docs/multiple-components.html#dynamic-children

http://facebook.github.io/react/docs/multiple-components.html#dynamic-children