suspend in render, not in reducers (#56497)
This removes our current convention of throwing promises in reducers in
favor of returning promises that can be consumed by `use` instead. This
will help unblock some future improvements (batching, PPR)
Reducers that would typically throw a promise now return their promise.
This gets maintained by a mutable queue (initialized in hydrate) to
ensure actions are processed in-order. The queue is also responsible for
mutating state and passing it as an input to subsequent actions.
This PR does not modify reducer behavior to keep changes minimal, but
there's more cleanup that we can do in a follow-up PR to remove things
that previously assumed reducers would be replayed.
(I recommend reviewing with whitespace turned off)
---------
Co-authored-by: Tim Neutkens <tim@timneutkens.nl>