React version: 18
Link to code example:
CodeSandbox
The expected behavior
Let's assume we have a increment function that first increments a local value, then a uSES value and then another local value like this:
function increment() {
setState1((x) => x + 1);
setUsesState((x) => x + 1);
setState2((x) => x + 1);
}
Now, there would be two ways this could behave that would be "intuitive for me":
- everything is batched:
[state1, usesState, state2] goes from [0,0,0] to [1,1,1]
- it batches until the "sync update" flushes the current batch:
[state1, usesState, state2] goes from [0,0,0] to [1,1,0] to [1,1,1]
The current behavior
Now, actual behaviour is different in React 18, depending on the "mode" React is currently in.
- in an event handler, everything is batched
[0,0,0] to [1,1,1] - no problem here
- outside an event handler, the
uSES setter is flushed first, then the local state changes are batched. [0,0,0] becomes [0,1,0] becomes [1,1,1] - this is very unintuitive for me.
- even inside a manual call wrapped in
unstable_batchedUpdates, we go [0,0,0] -> [0,1,0] -> [1,1,1]
Point 3 means that there is actually no way to even manually batch an update by uSES - but looking at point 1, React sometimes does so internally.
It seems that even in the non-batched situations, React does some batching: Calling setUsesState twice before calling setState2 will not lead to a [0,0,0] -> [0,1,0] -> [0,2,0] -> [1,2,1] situation, but to [0,0,0] -> [0,2,0] -> [1,2,1]
Up until now we had assumed that uSES would always behave like in 1., and we were only made aware of this by bug reports on react-redux.
Is this intended behaviour or a bug?
There might be some high priority update thing with a transition that I am missing here though - but either way this feels very breaking from older behaviour to me - and yes, I know that batchedUpdates has the unstable prefix ;)
React version: 18
Link to code example:
CodeSandbox
The expected behavior
Let's assume we have a
incrementfunction that first increments a local value, then auSESvalue and then another local value like this:Now, there would be two ways this could behave that would be "intuitive for me":
[state1, usesState, state2]goes from[0,0,0]to[1,1,1][state1, usesState, state2]goes from[0,0,0]to[1,1,0]to[1,1,1]The current behavior
Now, actual behaviour is different in React 18, depending on the "mode" React is currently in.
[0,0,0]to[1,1,1]- no problem hereuSESsetter is flushed first, then the local state changes are batched.[0,0,0]becomes[0,1,0]becomes[1,1,1]- this is very unintuitive for me.unstable_batchedUpdates, we go[0,0,0]->[0,1,0]->[1,1,1]Point 3 means that there is actually no way to even manually batch an update by
uSES- but looking at point 1, React sometimes does so internally.It seems that even in the non-batched situations, React does some batching: Calling
setUsesStatetwice before callingsetState2will not lead to a[0,0,0]->[0,1,0]->[0,2,0]->[1,2,1]situation, but to[0,0,0]->[0,2,0]->[1,2,1]Up until now we had assumed that
uSESwould always behave like in 1., and we were only made aware of this by bug reports onreact-redux.Is this intended behaviour or a bug?
There might be some high priority update thing with a transition that I am missing here though - but either way this feels very breaking from older behaviour to me - and yes, I know that
batchedUpdateshas theunstableprefix ;)