使用 setState 时如何立即获取更新状态?

Posted

技术标签:

【中文标题】使用 setState 时如何立即获取更新状态?【英文标题】:How do I get updated state immediately when using setState? 【发布时间】:2020-08-26 13:42:21 【问题描述】:

我有一个 ViewColumn 组件。我使用registerColumn 方法将列refs 存储在View 上下文中:

const [columns, setColumns] = useState([]);

const registerColumn = (node) => 
    const column = 
        someUniqueId: Math.random(),
        node,
        // more props
    ;

    setColumns(prev => [...prev, column])


const context = 
    columns,
    registerColumn


<ViewContext.Provider values=context>
    <View>
        <Column/>
        <Column/>
        <Column/>
    </View>
    <View>
        <Table/>
    </View>
</ViewContext.Provider>

我真正感到困惑的是Column 组件。每当我尝试注册该列并在之后获取更新的长度时,它都不会按时更新,因为setState 异步工作:

const columns, registerColumn = useContext(ViewContext);
const ref = useRef(null);

useEffect(() => 
    registerColumn(ref.current);

    // Here is where updated column length but it keeps saying it's 0 length
    console.log(`Hello from column number $columns.length`);
, []);

[...]

文档说,我可以使用 useEffectcolumns 作为依赖项,并在下次渲染时更新长度。但是,我需要在调用 registerColumn 后立即使用更新的状态 - 使用 another useEffect 基本上意味着破坏执行上下文和需要延迟任务,加上可能引入其他回调只是为了得到围绕这个。

我是 React 的新手,但我很确定还有其他方法可以解决这个问题,因此我们将不胜感激。

【问题讨论】:

【参考方案1】:

更新 useEffect 中的 setState 和 useEffect 中的控制台日志将不起作用,因为 useState 异步工作,并且对所有状态做出反应并更新一次。它正在更新状态,但它不会反映那个时刻,因为会通过更新对批次做出反应。 您可以使用其他具有列依赖的 useEffect,因此每次 registerColumn 更新时,都会调用第二个 useEffect 并控制台记录该值。

useEffect(() => 
    registerColumn(ref.current);
, []);


useEffect(() => 
    console.log(`Hello from column number $columns.length`);
,[columns]);

【讨论】:

问题是,正如您在我发布的 JSX 中看到的那样,那里有 3 列。安装后,这一切都发生得太快了,控制台消息会说同样的消息 3 次:Hello from column number 3 ignoring 1 和 2 :( 我看到很多次提到异步,但问题不是因为异步方法,你只是在记录一个stale closure。异步的 Setstate 在类组件中。 @HMR 我不相信这是真的。事实是useEffect 缺少columns 的依赖项,但是引入一个并没有改变,因为useState still works asynchronously

以上是关于使用 setState 时如何立即获取更新状态?的主要内容,如果未能解决你的问题,请参考以下文章

使用立即需要该状态进行 API 调用的 useState 挂钩时,如何等待 setState 调用完成?

为啥 React setState hook 没有立即更新? [复制]

在等待之后调用 setState 时,状态立即可用

如何知道所有 setState 更新是不是已应用于 React 组件中的状态?

自定义挂钩内的 setState 调用未更新状态

React setState注意事项