-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
clunky combine store usage #291
Comments
Hey, I actually agree with this problem. Unfortunately, it didn't reach a convincing good pattern.
But, I didn't know this use case. I'm happy to discuss if you or someone could take the lead on this topic. |
I will take a look through those other issues, cheers.
Assuming that's right ^, if you had a async fetch action in the store, and wanted to set By no means an expert on state management patterns, but happy to help keep the conversation going and contribute where I can. |
There's some good solutions in those issues you mentioned above. I've settled on using your const scopedSet = (ns, set) => (update) => {
set(prev => ({
[ns]: { ...prev[ns], ...(typeof update === 'function' ? update(prev[ns]) : update) }
}))
} I'm using it by passing the scoped setter as an extra arg into the stores: const useStore = create(devtools((set, get, api) => ({
users: createUsersStore(set, get, api, scopedSet('users', set)),
restrictedUsers: createRestrictedUsersStore(set, get, api, scopedSet('restrictedUsers', set))
})));
export const createUsersStore = (set, get, api, scopedSet) => ({
isFetching: false,
lastFetched: 0,
data: [],
fetch: async () => {
scopedSet(state => ({isFetching: !state.isFetching})); // state updater fn scopes as well
const data = await usersApi.getUsers();
scopedSet({data, isFetching: false, lastFetched: Date.now()});
return data;
}
}); #161 has alternative patterns for using scopedSet. Not sure I can contribute much else than has already been discussed in the other issues. The integrated solution in #178 looks promising, I would use it if it was a part of Zustand, but the simple solution above solves my problem just fine. |
That's good to hear. Some possible improvements for any volunteers would be:
|
because it's not scoped? #161 might help, but i'm not so sure. |
What about?
|
Im a few years late to the party, but there is this tool which would fit this case zustand-divisions |
I've followed the recommended way to combine stores in #228. It's clunky to work with as inside the stores you have to set state as if you're setting from the root of the state, this makes everything overly verbose. I imagine in many cases sub-stores won't touch other stores state and having one root store would mainly be for simplifying co-dependent state queries outside of the stores.
Take a root store made up of sub-stores like this:
Inside the sub-stores, it'd be intuitive to set state like this:
Example:
To fix this issue, you need to prepend all
set
object params with the sub-store key, and spread the current values:This feels like unnecessary ceremony. Immer could be a solution, but I like to have my async logic contained in store actions; Immer doesn't like async. The solution I've come to is a helper like this:
This helper can then be passed down into the stores
How setting now looks, and works intuitively:
This works well, but only supports
set(obj)
; no support forset(state => ...)
. Is there an alternative solution (or modification to mine) that matches this, and ideally doesn't limit the api ofset
. I feel a solution to this should be documented as in real world apps it's quite common to have co-dependent stores, and having one global store simplifies the application logic for these co-dependencies (imo).Zustand is fantastic, I want to harness the full power of it without introducing ridiculous ceremony like Redux.
The text was updated successfully, but these errors were encountered: