【发布时间】:2020-02-02 07:20:39
【问题描述】:
我有使用 React 上下文管理状态的 React 应用程序。我创建了简单的counter incrementation reproduction。
有两种情况。一个用于存储状态,第二个用于调度。这是取自 article 的模式。
状态上下文只存储单个数字,并且只能在此状态上调用一个操作:
function reducer(state: State, action: Action): State {
switch (action.type) {
case "inc": {
return state + 1;
}
}
}
我还有两个辅助函数用于同步和异步递增值:
async function asyncInc(dispatch: React.Dispatch<Action>) {
await delay(1000);
dispatch({ type: "inc" });
dispatch({ type: "inc" });
}
function syncInc(dispatch: React.Dispatch<Action>) {
dispatch({ type: "inc" });
dispatch({ type: "inc" });
}
下面是你在组件中使用它的方式:
const counter = useCounterState();
const dispatch = useCounterDispatch();
return (
<React.Fragment>
<button onClick={() => asyncInc(dispatch)}>async increment</button>
<button onClick={() => syncInc(dispatch)}>sync increment</button>
<div>{counter}</div>
</React.Fragment>
);
现在,当我单击sync increment 按钮时,一切都会按预期工作。它将调用inc 操作两次,计数器加2,并且只执行一次组件的重新渲染。
当我单击async increment 按钮时,它会先等待一秒钟并执行两次inc 操作,但它会重新渲染组件两次。
您必须打开控制台才能查看渲染组件的日志。
我有点明白为什么会这样。当它是同步操作时,一切都发生在组件渲染过程中,所以它会首先操作状态并在最后渲染。当它是异步操作时,它会先渲染组件,一秒钟后它会更新一次触发重新渲染的状态,然后会更新第二次触发下一次重新渲染。
那么是否可以只进行一次重新渲染来执行异步状态更新?在同一个复制中,有类似的例子,但使用 React.useState 也有同样的问题。
可以,我们以某种方式批量更新吗?或者我必须创建另一个操作来一次对状态执行多个操作?
我还创建了this reproduction,它通过采取一系列措施来解决这个问题,但我很好奇它是否可以避免。
【问题讨论】:
标签: reactjs react-hooks react-context react-state-management react-state