DEV Community

Cover image for How to use Zustand's persist middleware in Next.js

How to use Zustand's persist middleware in Next.js

Abdul Samad Ansari on March 14, 2023

In this article, we'll discuss the common error that arises when using Zustand's persist middleware with Next.js. You might have received errors li...
Collapse
 
ionellupu profile image
Ionel Cristian Lupu

How would you handle this case?

const [channelId, channelInfoLoaded, currencyCode, countryCode] = useStore(myStore, state => [
        state.channelId,
        state.channelInfoLoaded,
        state.currencyCode,
        state.countryCode,
    ])
Enter fullscreen mode Exit fullscreen mode

Because now the useStore returns undefined on first render.

Also, even if we use four individual useStores for every variable above, all of the values are undefined. Which means we have to add a ton of checks in JSX, right?

Collapse
 
abdulsamad profile image
Abdul Samad Ansari

Yes, I believe it would be beneficial to develop a Higher-Order Component (HOC) for performing checks or invoke the useStore function in the parent component with a single check and pass data as props in your case. We are redefining the store values after hydration, so we will have an undefined state initially. Let me know if you found any better way to tackle this problem.

Collapse
 
keshav263 profile image
Keshav Chhaparia

Hi
Did you find a solution to the same? I am also getting undefined on the first render. Adding checks on all the pages will be too tedious

Collapse
 
ionellupu profile image
Ionel Cristian Lupu

@keshav263 We added checks in our app. Fortunately, we had only two places where we had to modify the JSX and add the if statements. We didn't have to modify the entire app because the other components are rendered "later" in the rendering lifecyle due to us having loading screens. So by the time the loading screens disappear, the store has the values in it

Thread Thread
 
nobilelucifero profile image
Lucifero Von Nachtosphere

Question: how did you add your checks? I'm struggling to do it once functions are involved, too

Thread Thread
 
ionellupu profile image
Ionel Cristian Lupu

@nobilelucifero We ended up creating this hook and used it two-three times in the app:

/**
 * Use this function when you want to fix the "hydration" error in NextJS
 * @param store
 * @param callback
 */
export const useAsyncStore = <T, F>(store: (callback: (state: T) => unknown) => unknown, callback: (state: T) => F) => {
    const result = store(callback) as F
    const [data, setData] = useState<F>()

    useEffect(() => {
        setData(result)
    }, [result])

    return data
}
Enter fullscreen mode Exit fullscreen mode

In the code, it can be used like this:

const currencyCode = useAsyncStore(useAppContext, state => state.currencyCode)

return <>
   <div>... some other JSX you have here</div>
   {currencyCode? <TheComponentThatRequiresCurrencyCode currency={currencyCode}/>: undefined}
</>
Enter fullscreen mode Exit fullscreen mode

The check is just that if statement in the JSX

I am not recommending to used this too many times because it makes the JSX full of ternary operators like that. The reason we use it just three times is because we have a loading screen which waits for the backend data to load. In that time, the currency is already loaded and we don't need to do that ternary checks. We only have three places that don't have a loading section and that's why we used this custom hook three times.

Thread Thread
 
nobilelucifero profile image
Lucifero Von Nachtosphere

ahhh I see! It was simpler than what I was trying to (check to hydration and whether it was a variable or function). Amazing, thank you so so so much. I hope in a more proper solution soon too.

Collapse
 
shanehoban profile image
Shane Hoban

Awesome, this is the kind of solution I was looking for, linked it in this issue too: github.com/pmndrs/zustand/issues/938

Thanks!

Collapse
 
abdulsamad profile image
Abdul Samad Ansari

I'm glad it helped!

Collapse
 
nyctonio profile image
Ritesh Kumar

or maybe you can create a check for hydration render a loading.. while your ui do not get hydrated

Collapse
 
abdulsamad profile image
Abdul Samad Ansari

Yes. I think that should work as well.