Closed
Description
Based on:
- Investigate adding a proxy-based selector API
- useTrackedState from reactive-react-redux
- proxy-memoize
- why-did-you-update-redux
Proxy based solutions were floating around for a while, and actually actively used inside(MobX) and outside of React ecosystem(especially in Vue and Immer). I am opening this discussion to resolve status quo and add some momentum to Redux + Proxies investigations.
Overall proxies are capable to solve 3 objective:
- selector memoization. Proxies can be provide more efficient memoization(comparing to reselect) in some cases, where just some pieces of state matters, as seen in
proxy-memoize
orredux-tracked
import memoize from 'proxy-memoize';
// reading only `.a` and `.b`
const fn = memoize(x => ({ sum: x.a + x.b, diff: x.a - x.b }));
fn({ a: 2, b: 1, c: 1 }); // ---> { sum: 3, diff: 1 }
fn({ a: 3, b: 1, c: 1 }); // ---> { sum: 4, diff: 2 }
fn({ a: 3, b: 1, c: 9 }); // ---> { sum: 4, diff: 2 } (returning old value)
// ^ "c" does not matter
- testing. While the use case above is a little synthetic and such memoization is not really needed unless a developer willing not to use any memoization at all, it can be used to check selector quality, and report all selectors which react to the state change while they should not
technically running selector twice in dev mode might solve majority of the problems, like returning new array/object every time, proxy based memoization is capable to detect more complicated situations and provide some guidance around the problem. As seen in
why-did-you-update
- slice isolation. One named issue of redux is it's "global" store, and the fact that all listeners would be notified on state update. Knowing which slices were updated, and which selectors are listening for them, might provide an optimisation for selectors. This is actually a very old idea - Use React.createContext() with observed bits #1021 - but still valuable.
What proxies can solve:
- speed. Proxy based memoization works "more often" and might result a better experience
- less dev pain. Proxies "just works". At least, in the test mode, they can point on the problem instantly, not asking to invest some hours in debugging.
- TBD
What proxies cannot solve:
- per-component memoization. It's just absolutely orthogonal problem.
- TBD
What proxies can break:
- As long as one has to wrap
state
with a Proxy - one will useProxy
in all "frontend" code. In the same time at reducers/middleware side it will be juststate
. (Only once) I had a problem with "equal reference" memoization working differently inuseSelector
andsaga
. It's very edge-case-y, but having state sometimes wrapped, and sometimes not can break stuff.
Actionable items:
- decide about proxy-memoized selector
- decide about proxy-based selector pureness / quality checking
- decide about slice isolation or/and proxy-based tracking/DevTools integration. It's really possible to know which components reading which slice or/and react to a some piece of information and this knowledge can transform DevTools.
cc @markerikson , @dai-shi
Metadata
Metadata
Assignees
Labels
No labels