Persist redux value not working with next-redux-wrapper
See original GitHub issueDescribe the bug
I am useing redux-toolkit
, redux-persist
, next-redux-wrapper
.
When saving data to the storage space, it works normally.
But refresh page, the data not persisted…
To Reproduce
package.json
{
"name": "jebs-next",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "NODE_ENV='development' node server.js",
"build": "next build",
"start": "next start",
"lint": "next lint",
"format": "prettier --write \"src/**/*\"",
"local": "nodemon ./server.js localhost 3080"
},
"dependencies": {
"@hookform/resolvers": "^2.8.2",
"@reduxjs/toolkit": "^1.6.2",
"@types/parse-link-header": "^1.0.0",
"@types/react-redux": "^7.1.19",
"axios": "^0.22.0",
"babel-plugin-styled-components": "^1.13.2",
"browser-image-compression": "^1.0.16",
"express": "^4.17.1",
"google-map-react": "^2.1.10",
"next": "11.1.2",
"next-i18next": "^8.9.0",
"next-redux-wrapper": "^7.0.5",
"nodemon": "^2.0.4",
"parse-link-header": "^1.0.1",
"random-id": "^1.0.4",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-hook-form": "^7.17.2",
"react-hotkeys-hook": "^3.4.3",
"react-phone-input-2": "^2.14.0",
"react-redux": "^7.2.5",
"react-toastify": "^8.0.3",
"redux-persist": "^6.0.0",
"styled-components": "^5.3.1",
"styled-system": "^5.1.5",
"typescript": "4.4.3",
"yup": "^0.32.11"
},
"devDependencies": {
"@types/browser-image-compression": "^1.0.9",
"@types/google-map-react": "^2.1.3",
"@types/react": "17.0.27",
"@types/styled-components": "^5.1.14",
"@types/styled-system": "^5.1.13",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
"babel-eslint": "^10.1.0",
"eslint": "7.32.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.26.1",
"eslint-plugin-react-hooks": "^4.2.0",
"http-proxy-middleware": "^2.0.1",
"prettier": "^2.4.1"
}
}
rootReducer.ts
import { CombinedState, combineReducers } from '@reduxjs/toolkit'
import { HYDRATE } from 'next-redux-wrapper'
import { persistReducer } from 'redux-persist'
import storageSession from 'redux-persist/lib/storage/session'
import { KEY_SLICE_ROOT, KEY_SLICE_STORAGE } from '../../common/key'
import authenticationReducer, { AuthState } from './authSlice'
import chatsReducer, { ChatsState } from './chatsSlice'
import progressReducer, { ProgressState } from './progressSlice'
import storageReducer, { StorageState } from './storageSlice'
import userReducer, { UserState } from './userSlice'
const persistConfig = {
key: KEY_SLICE_ROOT,
storage: storageSession,
whitelist: [KEY_SLICE_STORAGE],
}
const rootReducer = (
state: any,
action: any,
): CombinedState<{
progress: ProgressState
authentication: AuthState
chats: ChatsState
storage: StorageState
user: UserState
}> => {
if (action.type === HYDRATE) {
return {
...state,
...action.payload,
}
}
return combineReducers({
progress: progressReducer,
authentication: authenticationReducer,
chats: chatsReducer,
storage: storageReducer,
user: userReducer,
})(state, action)
}
export type RootState = ReturnType<typeof rootReducer>
export default persistReducer(persistConfig, rootReducer)
store.ts
import { Action, configureStore } from '@reduxjs/toolkit'
import { createWrapper } from 'next-redux-wrapper'
import { persistStore } from 'redux-persist'
import { ThunkAction } from 'redux-thunk'
import reducer, { RootState } from './features'
const store = configureStore({
reducer,
devTools: process.env.NODE_ENV !== 'production',
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),
})
const makeStore = () => store
export type AppDispatch = typeof store.dispatch
export type AppThunk = ThunkAction<void, RootState, unknown, Action<string>>
export const persistor = persistStore(store) // Nasty hack
// next-redux-wrapper에서 제공하는 createWrapper정의
export const wrapper = createWrapper(makeStore, {
debug: process.env.NODE_ENV !== 'production',
})
export default store
_app.tsx
import { NextPage } from 'next'
import { appWithTranslation } from 'next-i18next'
import type { AppProps } from 'next/app'
import Head from 'next/head'
import 'react-phone-input-2/lib/bootstrap.css'
import { Provider } from 'react-redux'
import 'react-toastify/dist/ReactToastify.css'
import { PersistGate } from 'redux-persist/integration/react'
import { ThemeProvider } from 'styled-components'
import ProgressBar from '../components/ProgressBar'
import Spinner from '../components/Spinner'
import Toast from '../components/Toast'
import store, { persistor, wrapper } from '../store'
import '../styles/globals.css'
const App: NextPage<AppProps> = ({ Component, pageProps }) => {
return (
<>
<Head>
<title>jebs</title>
</Head>
<Provider store={store}>
<PersistGate persistor={persistor} loading={<Spinner />}>
<ThemeProvider
theme={{
breakpoints: ['501px', '769px', '1920px'],
}}
>
<ProgressBar />
<Toast />
<Component {...pageProps} />
</ThemeProvider>
</PersistGate>
</Provider>
</>
)
}
export default wrapper.withRedux(appWithTranslation(App))
storageSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { KEY_SLICE_STORAGE } from '../../common/key'
export interface StorageState {
accessToken: string | null
}
const initialState: StorageState = {
accessToken: null,
}
const storage = createSlice({
name: KEY_SLICE_STORAGE,
initialState,
reducers: {
saveAccessToken(state, action: PayloadAction<string>) {
state.accessToken = action.payload
},
},
})
export const { saveAccessToken } = storage.actions
export default storage.reducer
userSlice.ts
...
export const fetchConfirmPhoneCodeAndValues =
(uid: string, name: string, phone: string, code: string): AppThunk =>
async (dispatch) => {
try {
dispatch(loading())
const { statusCode, message } = await getCheckFindPWPhoneAndValues(
uid,
name,
phone,
code,
)
if (statusCode && statusCode === 200) {
toast.success(MESSAGE_CONFIRM_CODE_SUCCESS)
dispatch(confirmCodeSuccess())
dispatch(
saveAccessToken(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IlZ0Mm1NSXVqYkFoT0dHOC0iLCJpYXQiOjE2MzU5MTQ2E',
),
)
} else {
throw new Error(message ?? '')
}
} catch (err) {
if (err) {
const { message } = err as ErrorState
toast.error(message)
} else {
toast.error(ERROR_BASIC_MESSAGE)
}
}
}
...
Expected behavior
Even if the page is switched or refreshed, the value of accsses_token in storage must be maintained.
Screenshots
Before refresh or switch page
After refresh or switch page
Desktop (please complete the following information):
- OS: MacOS version 11.4
- Browser : chrome
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:6
Top Results From Across the Web
next.js - I have successfully implemented the redux-persist ...
You have to put inside that string array the redux reducers values you want to be persisted. Example: const persistConfig = { key:...
Read more >Cant use next-redux-wrapper with redux : r/nextjs - Reddit
the error I am facing : I can't use the ReturnType for the store to set up the next redux wrapper, any help?...
Read more >How to use Redux in Next.js - LogRocket Blog
Learn how to incorporate Redux, the most popular state management tool, into Next.js quickly and easily in this full tutorial.
Read more >hitorisensei/next-redux-wrapper v6.0.0 - npm.io
import React, {Component} from 'react'; import {NextPage} from 'next'; import {wrapper, State} from '../store'; // you can also use `connect()` instead of hooks ......
Read more >How to setup store and Redux Persist with Next.js for SSR
If you want to use Redux Persist with Next.js with SSR constraints, you have to follow some logic to make your code work...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I was hoping that repo had the solution, as it seemed promising. Unfortunately it doesn’t work, as the screen will still be white if javascript is disabled.
Also created an issue here: https://github.com/vercel/next.js/discussions/31884
It’s amazing how such a single feature turns out to be so challenging. Oh well, hence my username.
i got the same problem