首页 > 解决方案 > 事件处理程序的状态更新

问题描述

状态无需显式设置即可更新

我偶然跑到这里,这让我很困惑。据我所知,您执行以下操作:

1-创建当前状态的副本 2-修改副本 3-将修改后的副本分配给状态,从而更新它。

我就是这样做的,而且效果很好。

handleChange(index, event) {
    const {name, value} = event.target;
    this.setState((prevState) => {
        const newState = [...prevState.items];
        newState[index][name]= value;
        return{items: newState};
    });

但奇怪和令人困惑的是,下面的代码也可以工作,但不必像上面那样在最后一行显式分配它。只要我更新不是它的引用的副本,它就会更新。

handleChange(index, event) {
    const {name, value} = event.target;
    this.setState((prevState) => {
        const newState = [...prevState.items];
        newState[index][name]= value;

        return{}; //it works as long as I have the brackets.
    });

标签: javascriptreactjs

解决方案


从您问题中的代码来看,您的状态似乎具有类似于以下的结构:

状态= {项目:[{name1:'index0Value1',name2:'index0Value2'},{name1:'index1Value1',name2:'index1Value2'}]};

whereitems是一个对象数组。

当你这样做时:

const newState = [...prevState.items];

您仅复制数组,但newState数组中的对象仍与原始状态共享。因此,您可以在不影响原始对象的情况下将新对象推送到数组中,但是当您这样做时:

newState[index][name]= value;

您正在更改原始状态和新状态的对象。运行下面的代码片段来查看演示。

const prevState = { items: [{name1: 'index0Value1', name2: 'index0Value2'}, {name1: 'index1Value1', name2: 'index1Value2'}] };

document.getElementById('origbefore').innerHTML = 'prevState before='+JSON.stringify(prevState);

const newItems = [...prevState.items];
newItems[0]['name1']='tryingToOnlyChangeNewState';
const newState = { items: newItems };

document.getElementById('origafter').innerHTML = 'prevState after='+JSON.stringify(prevState);
document.getElementById('new').innerHTML = 'newState='+JSON.stringify(newState);
<div id="origbefore"></div>
<div id="origafter"></div>
<div id="new"></div>

因此,在这两个示例中,您的分配都在更改 prevState,并且由于setState支持传入与先前状态合并的部分状态,因此当您返回一个空对象时,React 会将其与突变的先前状态合并,然后重新渲染结果。


推荐阅读