atlassian / react-sweet-state

Shared state management solution for React
https://atlassian.github.io/react-sweet-state/
MIT License
871 stars 55 forks source link

Shareable container implementation #198

Closed albertogasparin closed 1 year ago

albertogasparin commented 1 year ago

Evolution after #196 discussion. We are inverting the Container / Store relationship. Now stores can link to a container via containedBy so containers can be shared across stores. Container actions also move to the createStore API (under handlers) so there is no need to distinguish between stores in a multi store containment situation. This also makes Containers extremely lightweight, as they can be imported anywhere in the tree without risking importing actions and other Store specific implementations. It will also enable erroring whenever a store should be containedBy but it is not (#190).

From:

const Store = createStore({
  initialState: { count: 0 },
  actions: { ... },
});

export const CounterContainer = createContainer(Store, {
  onInit: () => ...
});

to

export const CounterContainer = createContainer();

const Store = createStore({
  containedBy: CounterContainer,
  initialState: { count: 0 },
  actions: { ... },
  handlers: {
    onInit: () => ...,
  }
});

We will still support the old API, which now becomes a way to provide overrides in specific situations (eg tests). So if a store has containedBy but the subscribers render under a Container that was created explicitly with that store argument, such container will own the state even if it was not the one specified in containedBy. The risks of having both styles in a codebase should be minimal, and we can soft push to adopt the new pattern by promoting it by default on the docs and progressively move to it via linting and codemods.

albertogasparin commented 1 year ago

Please review @theKashey and @anacierdem 🙏🙏🙏🙏 (hopefully for the last time)

theKashey commented 1 year ago

Long story short:

And I really like how CounterContainer(from example) can provide props to all nested onInit functions, no matter how many stores are containedBy inside

theKashey commented 1 year ago
albertogasparin commented 1 year ago

Addressed the PR comments and published the reworked docs

theKashey commented 1 year ago

Quite solid work, you've invested much more effort than I anticipated, but the outcome is also proportionally better 🎉

theKashey commented 1 year ago

Last moment question - should handle behaviour for stores marked to be containedBy or let's keep this behavior for

Why:

If there was something to shout at me earlier - that would save 3 dev days 😉

albertogasparin commented 1 year ago

If there was something to shout at me earlier - that would save 3 dev days

Yes, that will come right after this PR. Didn't wanna overload this one too much because it already has lots of changes 😄 It will be "must be containedBy", and Registry will validate whenever store has that attribute and throw an async error if that registry is the global one.