Reactjs 反应状态行为

Reactjs 反应状态行为,reactjs,Reactjs,所以,最近我开始了一个新项目。我只使用功能组件(不确定这是否与本期相关) 我已经初始化了这样一个状态变量 const[selectedFields,setSelectedFields]=useState([]); 在下面的函数中,我更新状态 let sendMessage = (msg) => { let id = uuid4(); if (msg.key === 'text') { msg = {...Fields.Text, a

所以,最近我开始了一个新项目。我只使用功能组件(不确定这是否与本期相关)

我已经初始化了这样一个状态变量

const[selectedFields,setSelectedFields]=useState([]);

在下面的函数中,我更新状态

let sendMessage = (msg) => {
        let id = uuid4();
        if (msg.key === 'text') {
            msg = {...Fields.Text, action: 'addElement', style: Fields.styles, id};
        } else if (msg.key === 'email') {
            msg = {...Fields.Email, action: 'addElement', style: Fields.styles, id};
        } else if (msg.key === 'firstName') {
            msg = {...Fields.FirstName, action: 'addElement', style: Fields.styles, id};
        } else if (msg.key === 'lastName') {
            msg = {...Fields.LastName, action: 'addElement', style: Fields.styles, id};
        } else if (msg.key === 'dob') {
            msg = {...Fields.DoB, action: 'addElement', style: Fields.styles, id};
        } else if (msg.key === 'tel') {
            msg = {...Fields.Phone, action: 'addElement', style: Fields.styles, id};
        }
        console.log(selectedFields);
        setSelectedFields([...selectedFields, msg]);
        console.log(selectedFields);
        setTimeout(() => {
            console.log(selectedFields);
        }, 2000);
        iframeEl.contentWindow.postMessage(msg, '*');
    };
但是这三个
console.log
都会打印
[]
。 我做错了什么?蒂亚


仅供参考,React非常新,事实上这是我的第一个项目。

React状态更新是异步的,另外,状态更新会导致组件函数在更新完成后被调用,这意味着您将获得一个新的
selectedFields
变量。第一次调用组件时,原始的
selectedFields
变量一直保持不变。这就是为什么您的
setTimeout
版本都没有收到更改:它查看的是旧的
selectedFields
变量,而不是新变量

可以这样想:当组件处于一种状态时调用函数,然后当组件处于新状态时再次调用函数

您的函数应该使用
selectedFields
来呈现并为其发出状态更新,但函数中不应该包含期望这些状态更新已经发生的代码,除非它从
const[selectedFields,setSelectedFields]=useState([])获取新状态


另外,由于状态更新是异步的,并且可以“批量”进行,其中更新不会立即完成,并且在再次调用组件之前可能会发生另一次更新,因此此行通常不正确:

setSelectedFields([...selectedFields, msg]);
相反,您需要回调表单:

setSelectedFields(fields => [...fields, msg]);
这样,如果对批处理在一起的字段有多个更新,则以后的更新不会覆盖以前的更改

不幸的是,React文档不清楚何时需要使用状态设置器函数的回调版本以及何时可以在更新状态时直接使用状态。一些部分显示使用回调(
setCount(oldCount=>oldCount+1)
),其他部分显示直接更新(
setCount(count+1)
)。我做过,但不幸的是没有成功