react状态行为

IT技术 reactjs
2021-05-11 00:17:54

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

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

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的打印[]我究竟做错了什么?TIA。

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

1个回答

React 状态更新是异步的,另外,状态更新会导致您的组件函数在更新完成后被调用,这意味着您将获得一个 selectedFields变量。selectedFields一次调用您的组件时的原始变量从未改变这就是为什么甚至您的setTimeout版本也没有接受更改的原因:它正在查看旧selectedFields变量,而不是新变量。

可以这样想:您的函数在组件处于一种状态时被调用,然后在它处于新状态时再次调用。

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


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

setSelectedFields([...selectedFields, msg]);

相反,您需要回调表单:

setSelectedFields(fields => [...fields, msg]);

这样,如果对一起批处理的字段进行了多次更新,则后面的更新不会覆盖较早的更改。

不幸的是,React 文档并不清楚何时需要使用 state setter 函数的回调版本,何时可以在更新 state 时直接使用 state。有些部分显示使用回调 ( setCount(oldCount => oldCount + 1)),其他部分显示直接更新 ( setCount(count + 1))。试图得到这个答案,但不幸的是没有成功。