同一函数体中的 React 上下文更新被聚合为具有数据存储的单个事务,这是预期的行为吗?
React context updates in same function body are aggregated as a single transaction with data store, is this expected behavior?
虽然我最近使用 React Context
模式取得了成功,但我 运行 遇到了一个我想更好地理解的问题。
模式由下面 link 处的代码描述。本质上,我使用上下文 API 来创建一个单例 class。我喜欢这种模式,因为它保持不变性,但提供了一些不错的 OO 功能。
我 运行 遇到的问题是,如果在同一 ~member 函数中调用上下文 dispatch
更新,则它们不会单独传播。看起来它们正在聚合成一个 t运行saction。这对于某些场景中的性能非常有用。但是,这里不是那么多。
示例成员函数:
export const makeRunCapiProcess = (state : CapiContextI)=>(process : ()=>void)=>{
const capiProcessName = Shortid.generate();
state.dispatch({
type: "def",
payload: {
...state,
core : {
...state.core,
[capiProcessName] : process
}
}
})
process()
// !!!!!!!!!!!!!!!!!!!
// THIS IS THE PROBLEM AREA
// !!!!!!!!!!!!!!!!!!!
// Updates to context state are only propagated after this call.
// Can circumvent this by wrapping in async or using setTimeout,
// but that has resulted in a failure to set some proccesses to false.
// I have also tried using a state.forceUpdate() here, but to no avail.
state.dispatch({
type: "def",
payload: {
...state,
core : {
...state.core,
[capiProcessName] : false
}
}
})
return capiProcessName;
}
最小可重现示例: Check it out on CodeSandbox
如评论中所述,我可以通过 setTimeout
或 async
IIE 解决此问题,但这会导致其他问题。
我会注意到我正在使用 CRA default;我想知道这是否可能是一些聪明但不那么聪明的编译器技巧。
编辑 1: 正如现在在评论中指出的那样,我还尝试将 forceUpdate 成员添加到单例中。但是,这似乎是在两次调用之后调用的,因此没有解决我的问题。
编辑 2: 我仍然很好奇幕后发生的事情。但是,我认为这是一种过于迫切的模式。如果你发现这个 post 并且你正在寻找类似的东西,我认为通过提供某种状态变化然后触发提供者的 useEffect 中的清理来实现它通常会更好。
部分回答我自己的问题:
不要尝试 运行 在单个函数中更新多个上下文。它们是分批的。有关更多信息,请参阅 React GitHub 上的此线程:https://github.com/facebook/react/issues/21899
虽然我最近使用 React Context
模式取得了成功,但我 运行 遇到了一个我想更好地理解的问题。
模式由下面 link 处的代码描述。本质上,我使用上下文 API 来创建一个单例 class。我喜欢这种模式,因为它保持不变性,但提供了一些不错的 OO 功能。
我 运行 遇到的问题是,如果在同一 ~member 函数中调用上下文 dispatch
更新,则它们不会单独传播。看起来它们正在聚合成一个 t运行saction。这对于某些场景中的性能非常有用。但是,这里不是那么多。
示例成员函数:
export const makeRunCapiProcess = (state : CapiContextI)=>(process : ()=>void)=>{
const capiProcessName = Shortid.generate();
state.dispatch({
type: "def",
payload: {
...state,
core : {
...state.core,
[capiProcessName] : process
}
}
})
process()
// !!!!!!!!!!!!!!!!!!!
// THIS IS THE PROBLEM AREA
// !!!!!!!!!!!!!!!!!!!
// Updates to context state are only propagated after this call.
// Can circumvent this by wrapping in async or using setTimeout,
// but that has resulted in a failure to set some proccesses to false.
// I have also tried using a state.forceUpdate() here, but to no avail.
state.dispatch({
type: "def",
payload: {
...state,
core : {
...state.core,
[capiProcessName] : false
}
}
})
return capiProcessName;
}
最小可重现示例: Check it out on CodeSandbox
如评论中所述,我可以通过 setTimeout
或 async
IIE 解决此问题,但这会导致其他问题。
我会注意到我正在使用 CRA default;我想知道这是否可能是一些聪明但不那么聪明的编译器技巧。
编辑 1: 正如现在在评论中指出的那样,我还尝试将 forceUpdate 成员添加到单例中。但是,这似乎是在两次调用之后调用的,因此没有解决我的问题。
编辑 2: 我仍然很好奇幕后发生的事情。但是,我认为这是一种过于迫切的模式。如果你发现这个 post 并且你正在寻找类似的东西,我认为通过提供某种状态变化然后触发提供者的 useEffect 中的清理来实现它通常会更好。
部分回答我自己的问题:
不要尝试 运行 在单个函数中更新多个上下文。它们是分批的。有关更多信息,请参阅 React GitHub 上的此线程:https://github.com/facebook/react/issues/21899