React中使用react-redux、@reduxjs/toolkit状态管理工具
react-redux,@reduxjs/toolkit
- react-redux 是的官方 React UI 绑定层,它允许您的 React 组件从 Redux 存储中读取数据,并将操作分派到存储以更新状态。
React Redux 8.x 需要 React 16.8.3 或更高版本 / React Native 0.59 或更高版本,才能使用 React Hook
- @reduxjs/toolkit 是对 Redux 的二次封装,开箱即用的一个高效的 Redux 开发工具集,使得创建store、更新store等更简单。
快速开始
0、安装
在 create-react-app 应用中使用,此处使用版本:react v18.2.x、react-redux v8.0.x、@reduxjs/toolkit v1.8.x
$ npm i react-redux @reduxjs/toolkit
1、根组件配置store
// 入口 src/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import store from './store'
import { Provider } from 'react-redux'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
2、创建Reducer、Action
// src/store/dic.js
import { createSlice } from '@reduxjs/toolkit'
import baseApi from '../api/base'
// 使用createSlice方法创建一个slice。每一个slice里面包含了reducer和actions,实现模块化的封装
export const counterSlice = createSlice({
// 命名空间
name: 'dic',
// state数据的初始值
initialState: {
sortList: [
{ label: '食品类', value: '食品类' },
{ label: '服装类', value: '服装类' },
{ label: '日用品类', value: '日用品类' },
]
},
// 定义的action。由于内置了immutable插件,可以直接使用赋值的方式进行数据的改变
reducers: {
changeVal: (state, action) => {
// 第一个参数 state为当前state中的数据
// 第二个参数 action为 {payload: [{ label: '家具类', value: '家具类' }], type: "dic/changeVal"}
// payload 为传过来的新参数值
// type 为action触发类型
console.log('changeVal:', JSON.parse(JSON.stringify(state)), state, action)
state.sortList = action.payload
}
},
})
export const { changeVal } = counterSlice.actions
export default counterSlice.reducer
3、创建store
// src/store/index.js
import { configureStore } from '@reduxjs/toolkit'
import dic from './dic'
export default configureStore({
reducer: {
dic,
},
})
4、组件调用
// src/views/Goods.jsx
import { useSelector, useDispatch } from 'react-redux'
import { changeVal } from '@/store/dic'
function Goods (props) {
const dispatch = useDispatch()
// 使用state中的数据
const sortList = useSelector((state) => state.dic.sortList)
useEffect(() => {
// 触发store中action以更新数据
dispatch(changeVal([{ label: '家具类', value: '家具类' }]))
}, [])
return (
<div>
渲染数据:
<ul>
{
sortList.map(el => (
<li key={el.value}>{el.label}</li>
))
}
</ul>
</div>
)
}
export default Goods
异步操作
方式1
// src/store/dic.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import baseApi from '../api/base'
export const loadGoods = createAsyncThunk(
'dic/fetchGoods',
(data, thunkAPI) => {
// thunkAPI:一个对象,其中包含通常传递给 Redux thunk 函数的所有参数,以及其他选项(参考:https://redux-toolkit.js.org/api/createAsyncThunk#payloadcreator)
baseApi.findGoods(data).then(res => {
thunkAPI.dispatch(setGoods(res.result))
})
}
)
export const counterSlice = createSlice({
name: 'dic',
initialState: {
goodsData: [],
},
reducers: {
setGoods: (state, action) => {
state.goodsData = action.payload
}
},
})
export const { setGoods } = counterSlice.actions
export default counterSlice.reducer
方式2
// src/store/dic.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import baseApi from '../api/base'
export const loadGoods2 = createAsyncThunk(
'dic/fetchGoods2',
(data, thunkAPI) => {
return baseApi.findGoods(data).then(res => res.result)
}
)
export const counterSlice = createSlice({
name: 'dic',
initialState: {
goodsData: [],
},
reducers: {},
extraReducers: {
// 异步函数成功fulfilled时回调(类似的还有pending等待、rejected拒绝,此处只列举成功态)
[loadGoods2.fulfilled](state, action) {
state.goodsData = action.payload
},
}
})
// export const { } = counterSlice.actions
export default counterSlice.reducer
组件调用
// src/views/Goods.jsx
// 省略其它代码...
useEffect(() => {
dispatch(loadGoods({ name: '香蕉' }))
dispatch(loadGoods2({ name: '橘子' }))
}, [])
// 省略其它代码...