Next.js @reduxjs/toolkit redux-persist 之 6.0.0 版本持久化处理
集成公共状态管理插件
@reduxjs/toolkit react-redux redux-persist
store 之 index.ts 代码
import { configureStore } from '@reduxjs/toolkit'
import { useSelector, TypedUseSelectorHook, useDispatch, shallowEqual } from 'react-redux'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
// 引入一个新的 reducer
import reducers from './reducers'
// 这个是redux-persist 的配置,可以配置黑名单、白名单
const persistConfig = {
key: 'root', // 自动框架生产的根目录id 是root。不变
storage, // 这个是选择用什么存储,session 还是 storage
}
// 一个经过处理的reducer
const persistedReducer = persistReducer(persistConfig, reducers)
// 获取值的类型
type GetStateFnType = typeof store.getState
type IRootState = ReturnType<GetStateFnType>
type DispatchType = typeof store.dispatch
// 创建 store
export const store = configureStore({
reducer: persistedReducer,
// 无法序列化
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),
})
// 返回持久化对象
export const persistor = persistStore(store)
// 获取值
export const useAppSelector: TypedUseSelectorHook<IRootState> = useSelector
// 调用 dispatch 使用方法
export const useAppDispatch: () => DispatchType = useDispatch
// 进行值得浅层对比。如果值一样,就不更新值
export const useAppShallowEqual = shallowEqual
reducers 代码
import { combineReducers } from 'redux';
import globalReducer from '../modules/global'
export default combineReducers({
global: globalReducer
});
global 代码
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
const globalSlice = createSlice({
name: 'global',
initialState: {
currentUrl: '/sound',
},
reducers: {
changeCurrenttAction(state, { payload }: PayloadAction<string>) {
state.currentUrl = payload
},
},
})
export const { changeCurrenttAction } = globalSlice.actions
export default globalSlice.reducer
Layout 文件代码 === app.tsx 代码
- 从 redux-persist/integration/react 引入 PersistGate , 传递 persistor 文件
import React, { memo, Suspense } from 'react'
import type { FC, ReactNode } from 'react'
import { ThemeProvider } from 'styled-components'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'
import theme from '@/styles/theme'
import { LayoutWrapper } from './style'
import { store, persistor } from '../../store'
import AppHeader from '../app-header/index'
import AppFooter from '../app-footer/index'
interface IProps {
children?: ReactNode
}
const Layout: FC<IProps> = ({ children }) => {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<ThemeProvider theme={theme}>
<LayoutWrapper style={{ overflowX: 'hidden' }}>
<AppHeader />
<Suspense fallback={<AppHeader />}>
<main className="container">{children}</main>
</Suspense>
<AppFooter />
</LayoutWrapper>
</ThemeProvider>
</PersistGate>
</Provider>
)
}
// memo防止重复渲染
export default memo(Layout)
使用
import { useAppShallowEqual, useAppSelector, useAppDispatch } from '@/store'
import { changeCurrenttAction } from '@/store/modules/global'
// redux 数据
const { global: {currentUrl} } = useAppSelector((state) => state, useAppShallowEqual)
const userDispatch = useAppDispatch()
const handleUrl = (url: string): void => {
Router.push({
pathname: url,
})
// 使用 redux 方法
userDispatch(changeCurrenttAction(url))
}