Replies: 5 comments 20 replies
-
I would leave someone for showing a good pattern, but here's what would work: const useStore = create((set, get) => ({
countA: 0,
countB: 0,
incA: () => set(prev => ({ countA: prev.countA + 1 })),
incB: () => set(prev => ({ countB: prev.countB + 1 })),
incBoth: () => {
get().incA()
get().incB()
},
})) |
Beta Was this translation helpful? Give feedback.
-
I ended up having the same (or similar?) issue where I get two state updates instead of one and it gets messed up: {
streams: [a, b, c],
activeStreams: [a],
removeActiveStream: (stream) => {
set((draft) => {
draft.activeStreams = draft.activeStreams.filter((x) => x !== stream);
});
},
stopAllStreams: () => {
set((draft) => {
draft.streams.forEach((stream) => {
if (stream.isActive()) {
stream.stop();
stream.clearFrameCallbacks();
draft.removeActiveStream(stream);
}
});
});
}
} I was hoping that calling I guess this is because the inner I need to replace I'd like to avoid more bloat by extracting it into something like: function removeActiveStream(draft: State, stream: Stream) {
draft.activeStreams = draft.activeStreams.filter((x) => x !== stream);
}
{
removeActiveStream: (stream) => {
set((draft) => removeActiveStream(draft, stream));
},
stopAllStreams: () => {
set((draft) => {
draft.streams.forEach((stream) => {
if (stream.isActive()) {
stream.stop();
stream.clearFrameCallbacks();
removeActiveStream(draft, stream);
}
});
});
},
} |
Beta Was this translation helpful? Give feedback.
-
I tried to clean things up by declaring a value called action at first, then use it like in below example.
But I got this error: |
Beta Was this translation helpful? Give feedback.
-
I think I'm facing the same issue but it only happens when I nest multiple actions using I query a tree structure, and I'm using zustand as a cache. When i'm updating the cache, I need to do some operations. Also this cache can be updated from different sides (for instance the cache of "companies" can get an update when querying directly companies, or when querying "currentEmployee.company" Imagine something like this
So basically whenever I get employees I update the cache of the employees, and then the cache of the companies I got from those units. And the equivalent when getting companies. The problem with this it that this generates a nesting of Not sure how to fix this, so far I'm trying a version where I have only a parent fn with set((state) => and make all the others accept state as a property, but it would be nice to be able to nest those actions and let immer mutate the draft and send everything at the end |
Beta Was this translation helpful? Give feedback.
-
It seems that the discussion didn't provide an explanation about the root cause of the issue, so I investigated a bit more. From what I gathered, the immer Zustand middleware uses immer's produce function. About nesting immer produces: Nesting multiple produce functions can result in incorrect states as the output of the inner produce is not used in the outer produce. As zustand actions return type is void, unfortunately we cannot use the inner action's result in the outer action to set the new state, so nesting actions (or immer produces) is not a way to go. Nesting can be avoided by @ivancuric's suggestion here: OR if you can, compose the code so that you don't really need to nest actions. |
Beta Was this translation helpful? Give feedback.
-
I've got a data structure which is a directed graph, with nodes and connections.
If I want to delete a node, I also need to delete the associated connections. Same goes for deleting multiple nodes at the same time.
So I've got zustand actions (I guess that's the term for store functions that use
set
?) for:etc.
So both
deleteNode
anddeleteMultipleNodes
are usingdeleteConnection
, anddeleteMultipleNodes
is basically usingdeleteNode
in a loop.How would you handle actions calling other actions in Zustand? Not sure what the correct terminology for this is, but I haven't found any documentation about it.
Beta Was this translation helpful? Give feedback.
All reactions