Add section for usage of persist middleware with NextJS (#1782)

* Add section for usage of persist middleware with NextJS

I have spent the last 1h30m trying to find the solution for `Hydration failed because the initial UI does not match what was rendered on the server` and after digging a lot I found the solution.
So i thought: Maybe this could be on official documentation!
So I made it. It's just copy and paste but at least it will be easier for future folks trying to solve the same problem

* ran yarn prettier

* fix typos

* Update docs/integrations/persisting-store-data.md

Co-authored-by: Blazej Sewera <code@sewera.dev>

* splitting long lines into smaller ones

following the suggestion of PR

* commit suggestion of changes in PR

Co-authored-by: Blazej Sewera <code@sewera.dev>

* commit suggestion of changes in PR

Co-authored-by: Blazej Sewera <code@sewera.dev>

* commit suggestion of changes in PR

Co-authored-by: Blazej Sewera <code@sewera.dev>

* commit suggestion of changes in PR

Co-authored-by: Blazej Sewera <code@sewera.dev>

* applying changes requested in PR

---------

Co-authored-by: Blazej Sewera <code@sewera.dev>
This commit is contained in:
Nipodemos 2023-05-07 20:25:00 -03:00 committed by GitHub
parent 639aa00699
commit 65d2bc0660
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -452,6 +452,75 @@ If your app does depends on the persisted state at page load,
see [_How can I check if my store has been hydrated_](#how-can-i-check-if-my-store-has-been-hydrated)
in the [FAQ](#faq) section below.
### Usage in Next.js
NextJS uses Server Side Rendering, and it will compare the rendered component on the server with the one rendered on client.
But since you are using data from browser to change your component, the two renders will differ and Next will throw a warning at you.
The errors usually are:
- Text content does not match server-rendered HTML
- Hydration failed because the initial UI does not match what was rendered on the server
- There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering
To solve these errors, create a custom hook so that Zustand waits a little before changing your components.
Create a file with the following:
```ts
// useStore.ts
import { useState, useEffect } from 'react'
const useStore = <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
}
export default useStore
```
Now in your pages, you will use the hook a little bit differently:
```ts
// useBearStore.ts
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
// the store itself does not need any change
export const useBearStore = create(
persist(
(set, get) => ({
bears: 0,
addABear: () => set({ bears: get().bears + 1 }),
}),
{
name: 'food-storage',
}
)
)
```
```ts
// yourComponent.tsx
import useStore from './useStore'
import { useBearStore } from './stores/useBearStore'
const bears = useStore(useBearStore, (state) => state.bears)
```
Credits: [This reply to an issue](https://github.com/pmndrs/zustand/issues/938#issuecomment-1481801942), which points to [this blog post](https://dev.to/abdulsamad/how-to-use-zustands-persist-middleware-in-nextjs-4lb5).
## FAQ
### How can I check if my store has been hydrated