反应状态更新不正确

Posted

技术标签:

【中文标题】反应状态更新不正确【英文标题】:React state updates incorrectly 【发布时间】:2020-02-27 09:28:17 【问题描述】:

预期:我正在尝试访问变量中的状态数据并操作该变量。我将再次将操纵日期设置为 setstate。

问题:当我将状态分配给变量时,而不是仅仅复制状态中的数据,它会成为状态本身的副本,因此当我操作数据时,状态本身就会发生变化。

注意:在下面的代码中,tmpData.splice 是我更改 tmpData 变量时状态发生变化的地方。

onRowAdd: newData => new Promise(resolve => 
    setTimeout(() => 
        
        const  data  = this.state;
        const tmpData = data;
        const tmpRowData = this.getRowData(this.state.valorenVal ? this.state.valorenVal : newData.nr ? newData.nr : '');
        if (tmpRowData.length >= 1) 
            if (newData.number && tmpRowData[0].nr) 
                tmpRowData[0].number = newData.number ? newData.number : '';

                tmpData.splice(tmpData.length, 0, tmpRowData[0]);

                this.setState( data: tmpData , () => resolve());
                this.setState( valorenVal: '' );
             else 
                this.setState( data , () => resolve());
            
         else 
            this.setState( data , () => resolve());
        
        
        resolve();
    , 1000);
),

我是 React 新手,这可能是一个愚蠢的问题,但你的回答将帮助我更好地理解 React。

【问题讨论】:

【参考方案1】:

在 React 中,您需要避免使用 direct state mutations,因为它会阻止 React 准确跟踪发生的更改。假设data 是一个数组,您可以像这样创建它的副本:

const tmpData = [...data];

const tmpData = Array.from(data);

并在使用setState 更新状态之前尽可能多地对其进行编辑,而不会导致不需要的突变

【讨论】:

【参考方案2】:

tmpDatadata 的浅拷贝。由于来自tmpData 的引用是通过浅拷贝从data 维护的,这就是为什么你仍在变异data

尝试以下方法:

const tmpData = data.slice()

这会创建一个新数组,它应该会中断对原始数组的引用,让您可以做任何您想做的事情来创建data 的下一个状态。希望对你有帮助

【讨论】:

【参考方案3】:

React 使用浅比较来检查当前 props 和 nextProps 对象以及当前 state 和 nextState 对象是否相等。这意味着如果状态中的所有键具有相同的值,React 将永远不会重新渲染组件。

在你的代码中tmpData等于data,它们都是同一个Object的索引。

function shallowEqual(state, nextState) 
    if ( state === nextState) 
        return true; 
    

    return Object.keys(state).every(key => state[key] === nextState[key]);

【讨论】:

以上是关于反应状态更新不正确的主要内容,如果未能解决你的问题,请参考以下文章

如何正确更新反应钩子状态中的数组

如何正确更新处于反应状态的对象或数组[重复]

反应状态没有在 SetInterval 方法中正确更新

反应:组件状态不更新记分员或计数器

修改状态和更新减速器的正确方法? (反应/还原)

更新反应状态而不覆盖先前的状态