中文文档 https://cn.redux.js.org/introduction/getting-started/#redux-toolkit
# NPM
npm install @reduxjs/toolkit react-redux
# Yarn
yarn add @reduxjs/toolkit react-redux
基本使用
//store/features/counterSlice.ts
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
count: 1,
},
reducers: {
increment(state, { payload }) {
state.count = state.count + payload
},
decrement(state) {
state.count -= 1
}
}
})
export const { increment, decrement } = counterSlice.actions
export default counterSlice.reducer
//store/index.ts
import { configureStore } from '@reduxjs/toolkit'
import counterSlice from './features/counterSlice'
const store = configureStore({
reducer: {
conter: counterSlice,
}
})
export default store
export type RootState = ReturnType<typeof store.getState>
全局引入
//index.tsx
import store from './store';
import { Provider } from 'react-redux'
<Provider store={store}>
<App />
</Provider>
页面使用
//views/RedexToolkit.tsx
import { useSelector, useDispatch } from 'react-redux'
import { RootState } from '../../store'
import { increment, decrement } from '../store/features/counterSlice'
export default function RedexToolkit() {
const { count } = useSelector((state: RootState) => state.conter)
const dispatch = useDispatch()
return (
<div>
{count}
<Button type="primary" onClick={() => { dispatch(decrement()) }}>
减
</Button>
<Button type="primary" onClick={() => { dispatch(increment(2)) }}>
加
</Button>
</div>
)
}
持久化存储
npm install redux-persist
//store/index.ts
import { configureStore, combineReducers } from '@reduxjs/toolkit'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import counterSlice from './features/counterSlice'
export const rootReducer = combineReducers({
conter: counterSlice,
})
const persistConfig = {
key: 'root',
storage,
}
const myPersistReducer = persistReducer(persistConfig, rootReducer)
export const store = configureStore({
reducer: myPersistReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
})
})
export const persistor = persistStore(store)
export type RootState = ReturnType<typeof store.getState>
PersistGate
是 redux-persist
提供的一个组件,它的主要作用是阻塞应用渲染,直到持久化状态被加载完毕。这意味着,在应用加载时,如果之前有保存的状态,那么 PersistGate
会等待这些状态从本地存储中加载,然后再渲染应用。如果没有使用 PersistGate
,那么在状态加载完成之前,应用可能会显示一个不完全的状态或空白页面。
不使用 PersistGate
可能会导致应用在状态加载完成之前显示一个不完全或不一致的状态。因此,在实际应用中,通常建议使用 PersistGate
来确保用户在应用加载时看到的是一个完整和一致的状态。
//index.ts
import { PersistGate } from 'redux-persist/integration/react'
import { store, persistor } from './store';
import { Provider } from 'react-redux'
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
异步
//store/features/counterSlice.ts
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
export const fetchList = createAsyncThunk(
'counter/fetchList', () => {
return new Promise<any>((resolve) => {
fetch('http://localhost:3001').then(async (res) => {
const res1 = await res.json()
resolve(res1)
})
})
}
)
export const counterSlice = createSlice({
name: 'counter',
initialState: {
count: 1,
title: 'resad',
status: '',
data: [],
error: ''
},
reducers: {
increment(state, { payload }) {
state.count = state.count + payload
},
decrement(state) {
state.count -= 1
}
},
extraReducers(builder) {
builder
.addCase(fetchList.pending, (state, action) => {
state.status = 'loading'
})
.addCase(fetchList.fulfilled, (state, action) => {
state.status = 'succeeded'
state.data = action.payload.message
})
.addCase(fetchList.rejected, (state, action) => {
state.status = 'failed'
state.error = action.payload.message
})
}
})
export const { increment, decrement } = counterSlice.actions
export default counterSlice.reducer
页面使用
import { fetchList } from '../store/features/counterSlice'
import { RootState } from '../store'
export default function RedexToolkit() {
const { tatus, error, data } = useSelector((state: RootState) => state.conter)
const dispatch = useDispatch()
return (
<div>
{status}{error}{data}
<Button type="primary" onClick={() => { dispatch(fetchList() as any) }}>
请求
</Button>
</div>
)
}