-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
What's the best approach when creating/composing nested stores? #163
Comments
I can think of a) creating a store in React lifecycle but I'd not recommend because it's easy to violate rules of hooks, b) creating multiple vanilla stores and composing them but that can be messy with Does something like this work for you? const useUsers = create((set, get) => ({
users: [],
createUser: (userProps) => {
const userId = createUniqueId()
const user = {
...userProps,
userId,
setStatus: (status) => {
set({
users: get().users.map((u) => u.userId === userId ? { ...u, status } : u),
})
},
}
set({
users: [...get().users, user],
})
},
}) |
@dai-shi Hi there, thank you very much for your reply. Yes, I think keeping it to one store is the most suitable approach for the time being. Your solution is also very helpful. Thanks 👍 |
@dai-shi I came up with a solution which means that child objects can remain unaware of the structure of a parent store. The implementation passes a custom set method which passes the child's state instead of the parent store state. As a sidenote, I'm using immer for state updates and Maps instead of arrays to avoid having id props on children. Here's a code sandbox demo: https://codesandbox.io/s/zustand-reference-passing-6r09r?file=/src/App.js:110-829 const createUser = (props, set, name) => ({
name,
...props,
setName: (name) => {
set((state) => {
state.name = name;
});
}
});
const useDatabase = create((set, get) => ({
users: new Map(),
addUser: (name) => {
const id = createID();
// Set method passed to child passes the user itself as state.
const childSet = (fn) => {
set((state) => {
fn(state.users.get(id));
});
};
const remove = () => {
set((state) => {
state.users.delete(id);
});
};
const newUser = createUser({ remove }, childSet, name);
set((state) => {
state.users.set(id, newUser);
});
},
getUsers: () => Array.from(get().users.values())
})); |
Hi |
My main problem is that even if I nest one store in another, the basic store methods (getState, setState) are exposed as opposed to its state and methods that would be returned from a hook call. Since I am unable to initialize a hook in a store, how do I properly tackle composing stores within other stores?
As an example, I would like to create a store containing an array of users. Each user would also be an individual store with state and methods. Then, in a component I could access the users and call their methods independently. For example in pseudo-code:
I've thought about passing the set method from the parent store but that seems to create too much coupling between stores. I've thought about creating one monolithic store but that would be quite messy. Perhaps I'm missing something obvious but I'm not sure how to tackle this problem.
The text was updated successfully, but these errors were encountered: