使用 setState 时如何立即获取更新状态?
Posted
技术标签:
【中文标题】使用 setState 时如何立即获取更新状态?【英文标题】:How do I get updated state immediately when using setState? 【发布时间】:2020-08-26 13:42:21 【问题描述】:我有一个 View
和 Column
组件。我使用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`);
, []);
[...]
文档说,我可以使用 useEffect
和 columns
作为依赖项,并在下次渲染时更新长度。但是,我需要在调用 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 没有立即更新? [复制]