The result of getSnapshot should be cached to avoid an infinite loop #1936
-
I'm new to zustand. I've got my basic functionality working, but I'm seeing this warning coming from
The stack trace is not very helpful, but I'm not directly using Is this a zustand bug or should I be scrutinizing my own code more? |
Beta Was this translation helpful? Give feedback.
Replies: 15 comments 31 replies
-
Are you creating a fresh store in render function? |
Beta Was this translation helpful? Give feedback.
-
my suggestion would be to use "useShallow" Docs const [blah] = useMyStore(useShallow((state) => [state.blah])); |
Beta Was this translation helpful? Give feedback.
-
my case is |
Beta Was this translation helpful? Give feedback.
-
I'm having a similar issue after upgrading from 4.5.2 to 5.0.0 In my case I was doing:
I was able to confirm I tried useShallow and it didn't work. (still getting infinite loop error) I implemented a workaround by separating the accessors into different hooks:
I feel like pulling each variable individually is an unintended restriction though, and I'd personally prefer not to have to decide whether to use useShallow everytime FWIW |
Beta Was this translation helpful? Give feedback.
-
Similar case with useShallow here: I had this selector:
Worked fine on v4, but on v5 I need to use |
Beta Was this translation helpful? Give feedback.
-
I have same problem when upgrade to v5, v4 working greate |
Beta Was this translation helpful? Give feedback.
-
same problem here. whether adding Downgrading to v4 solved the problem, without any code changes. |
Beta Was this translation helpful? Give feedback.
-
if shallow is not enough, try export function useDeepEqual<S, U>(selector: (state: S) => U): (state: S) => U {
// https://github.com/pmndrs/zustand/blob/main/src/react/shallow.ts
const prev = useRef<U>(undefined);
return (state) => {
const next = selector(state);
return deepEqual(prev.current, next) ? (prev.current as U) : (prev.current = next);
};
} |
Beta Was this translation helpful? Give feedback.
-
In my case it was the new empty array generation inside selector: Infifite loop code:
Fixed code:
|
Beta Was this translation helpful? Give feedback.
-
🚀 Hey folks! Give Kosha a try — https://www.npmjs.com/package/kosha 👉 If you're using plain Zustand without middleware, migrating is super simple: import { create } from "zustand" with import { create } from "kosha" ✅ And if you’re using the TypeScript double-call syntax like create<T>(set => ({...})) That’s it — you’re good to go! |
Beta Was this translation helpful? Give feedback.
-
Thanks for the feedback. You are correct, it doesn't have plugin
eco-system. As I mentioned earlier, straightforward replacement is for most
users who don't use any middlewares.
Yes. Json.stringify works, if any specific concerns could you please let
me know. Thanks.
Mayank Kumar Chaudhari
Software Architect (Focus Front End) | Microsoft Certified Expert
https://mayank-chaudhari.vercel.app/
…On Thu, 5 Jun, 2025, 10:05 am Danilo Britto, ***@***.***> wrote:
Doesn't look like production ready. But important:
- is not a straight forward replacement
- only persist middleware is available
- use json.stringify to compare values
- console.log everywhere
- seems like a copy/paste from Zustand with few changes IMHO
—
Reply to this email directly, view it on GitHub
<#1936 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGCR4VICG56F4K2L3TUDXKL3B7CJZAVCNFSM6AAAAABOZP34LWVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTGMZXGQ2TKNY>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
In most use cases, selectors return small objects or arrays.
Secondly, just double confirmed ` JSON.stringify({a: new Date()})` returns
` {"a":"2025-06-05T15:54:24.279Z"}`
Thanks for pointing out `Set` and `Map`. It's very rare. But still I shall
update this in documentation. Should not use `kosha` if you want to store
`Set` or `Map` to global store.
Mayank Kumar Chaudhari
Software Architect (Focus Front End) | Microsoft Certified Expert
https://mayank-chaudhari.vercel.app/
…On Thu, Jun 5, 2025 at 9:18 PM Danilo Britto ***@***.***> wrote:
JSON.stringify does not support Map, Date, Set and is expensive on large
objects so is really bad using it for comparisons where you need to compare
two objects many times
—
Reply to this email directly, view it on GitHub
<#1936 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGCR4VOCYFKDE5RNAIBW4MT3CBRDRAVCNFSM6AAAAABOZP34LWVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTGMZYGE2DSNA>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
That will not happen as we are comparing results of the same selector
function - order is preserved.
Mayank Kumar Chaudhari
Software Architect (Focus Front End) | Microsoft Certified Expert
https://mayank-chaudhari.vercel.app/
…On Thu, 5 Jun, 2025, 9:47 pm Danilo Britto, ***@***.***> wrote:
Most important if for some reason the keys are in different order the
comparison is false so using JSON.stringify is not good
—
Reply to this email directly, view it on GitHub
<#1936 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGCR4VOKFM3QNI3NJI42VVD3CBUQLAVCNFSM6AAAAABOZP34LWVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTGMZYGE4DINQ>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
the problem : Root cause: solution: my preferred solution: function useTodosMeta() { |
Beta Was this translation helpful? Give feedback.
-
Why not add the memorization (shallow & deepEquation) as a default? If all you want is just a simple primitive, there's really no need to use a 3rd party state management. |
Beta Was this translation helpful? Give feedback.
Thank you, I figured it out. The problem was that I was using
useX
callbacks to get around some eslint errors about the use ofuseX
hooks outside react components. The actual solution was: