Next.js Discord

Discord Forum

Next 13 - localStorage - Redux Toolkit - Middleware

Answered
Brown bear posted this in #help-forum
Open in Discord
Brown bearOP
Hi i'm learning Next 13 and Redux toolkit, currently i have this redux toolkit store, inside of it i have a middleware which controls the localStorage, the thing is, when i try to access localStorage with the initialState of the slice it causes two scenarios because of slice being server side rendered,
- The initial state checks if it's currently on client component and retrieves the localStorage info but it causes this error in the vscode console:
You must provide an initialState value that is not undefined. You may have misspelled initialState
error node_modules\redux\lib\redux.js (481:0) @ eval
error Error: The slice reducer for key "finishedBooks" returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined. If you don't want to set a value for this reducer, you can use null instead of undefined.
at Array.forEach (<anonymous>)
at eval (./src/store/index.ts:29:79)
at Module.(ssr)/./src/store/index.ts (C:\Users\Rito\Documents\prueba-tecnica-1-midudev.next\server\app\page.js:1997:1)
at webpack_require (C:\Users\Rito\Documents\prueba-tecnica-1-midudev.next\server\webpack-runtime.js:33:43)
at eval (./src/app/client.tsx:10:70)
at Module.(ssr)/./src/app/client.tsx (C:\Users\Rito\Documents\prueba-tecnica-1-midudev.next\server\app\page.js:1733:1)
at webpack_require (C:\Users\Rito\Documents\prueba-tecnica-1-midudev.next\server\webpack-runtime.js:33:43)
null

- The second case is the same, but if the component isn't rendered on the client-side, it returns an empty array while the page loads. However, it causes three errors, which I have attached in the images. Any idea of how i can solve it? I can't use a useEffect in the slice, and "use client" doesn't work either, returning null instead of the empty array doesn't work too
Answered by Dwarf Crocodile
I suspect you are using the App Router, since you are on Next.js 13 and talking about "use client". In regards to Redux, I recommend looking into this comment by the maintainer of the next-redux-wrapper that succintly describes using Redux and App Router:

This library will not work with new app structure. In fact, app structure makes redux usage really awkward and I do not recommend to do it. Since any server component can dispatch actions on server side, we will have to constantly sync redux state from server to client, which I find awkward.

My recommendation would be to clearly separate server state from client state and only update server state on server and redux (client) state on client. You will save yourself a lot of hours on not doing debugging of mixed state ;)

https://github.com/kirill-konshin/next-redux-wrapper/issues/494

Generally, I think most people in your situation would just have their initial state be an empty list, and use useEffect to update the state on the client when the component mounts, but you mentioned you can't do that.

Since you're using local storage, I suspect the redux-persist library may be useful, which allows you to persist and rehydrate a Redux store. It also defaults to using localStorage. See https://www.npmjs.com/package/redux-persist

Unfortunately, I can't offer any solutions other than trying to see how you can organize your code that ensures server state matches client state, so you don't have any hydration errors.
View full answer

1 Reply

Dwarf Crocodile
I suspect you are using the App Router, since you are on Next.js 13 and talking about "use client". In regards to Redux, I recommend looking into this comment by the maintainer of the next-redux-wrapper that succintly describes using Redux and App Router:

This library will not work with new app structure. In fact, app structure makes redux usage really awkward and I do not recommend to do it. Since any server component can dispatch actions on server side, we will have to constantly sync redux state from server to client, which I find awkward.

My recommendation would be to clearly separate server state from client state and only update server state on server and redux (client) state on client. You will save yourself a lot of hours on not doing debugging of mixed state ;)

https://github.com/kirill-konshin/next-redux-wrapper/issues/494

Generally, I think most people in your situation would just have their initial state be an empty list, and use useEffect to update the state on the client when the component mounts, but you mentioned you can't do that.

Since you're using local storage, I suspect the redux-persist library may be useful, which allows you to persist and rehydrate a Redux store. It also defaults to using localStorage. See https://www.npmjs.com/package/redux-persist

Unfortunately, I can't offer any solutions other than trying to see how you can organize your code that ensures server state matches client state, so you don't have any hydration errors.
Answer