反应状态行为 [英] React state behavior

查看:45
本文介绍了反应状态行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

So, recently I've started a new project. I'm only using functional components (not sure if that's a relevant statement for this issue).

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

I have initialized a state variable like this

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

在波纹管函数中,我更新状态

In bellow function, I update the state

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.

But all three console.log's prints []. What am I doing wrong? TIA.

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

FYI, very new to React, in fact this is my first project.

推荐答案

React 状态更新是异步,另外,状态更新会导致您的组件函数在更新完成后被调用,即意味着你得到了一个 new selectedFields 变量.第一次调用组件时的原始 selectedFields 变量永远不会改变.这就是为什么即使您的 setTimeout 版本也没有进行更改:它查看的是旧的 selectedFields 变量,而不是新的变量.

React state updates are asynchronous and, separately, a state update results in your component function being called once the update has completed, which means you get a new selectedFields variable. The original selectedFields variable the first call to your component has never changes. That's why even your setTimeout version didn't pick up the change: It's looking at the old selectedFields variable, not the new one.

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

Think of it this way: Your function is called when the component is in one state, and then called again when it's in a new state.

你的函数应该使用 selectedFields 来呈现,并为它发出状态更新,但它不应该有代码期望那些状态更新已经发生,而不是从它获取新状态const [selectedFields, setSelectedFields] = useState([]); 行.

Your function should use selectedFields to render, and issue state updates for it, but it should not have code in it that expects those state updates to have occurred other than that it gets the new state from the const [selectedFields, setSelectedFields] = useState([]); line.

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

Separately, because state updates are asynchronous and can be "batched" where an update isn't done immediately and it's possible for another one to occur before your component is called again, this line is often incorrect:

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

相反,您需要回调表单:

Instead, you need the callback form:

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

这样,如果对一起批处理的字段进行多次更新,后面的更新不会覆盖前面的更改.

That way, if there are multiple updates to the fields that are batched together, later ones don't overwrite the changes from earlier ones.

不幸的是,React 文档并不清楚何时需要使用 state setter 函数的回调版本,以及何时可以在更新 state 时直接使用 state.有些部分显示使用回调(setCount(oldCount => oldCount + 1)),其他部分显示直接更新(setCount(count + 1)).我已经尝试获得有关此问题的答案,但不幸的是没有成功.

Unfortunately, the React documentation is unclear about when you need to use the callback version of the state setter function and when you can use state directly when updating state. Some parts show using the callback (setCount(oldCount => oldCount + 1)), others show updating directly (setCount(count + 1)). I've tried to get an answer on this, but unfortunately haven't been successful.

这篇关于反应状态行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆