@reduxjs/toolkit
这是React官网推荐的Redux公共状态管理工具
官网地址: cn.redux.js.org/introductio...
Demo GIt: gitee.com/tcwty123/re... 分支: @reduxjs/toolkit
相比于最原始的Redux,redux toolkit最大的特点是:
基于切片机制,把reducer和actionCreator混合在一起了,并且内部集成了immer 不需要克隆一份state

1. 下载
js
yarn add react-redux
yarn add yarn add @reduxjs/toolkit
2. 目录结构

3. 文件编写内容
Index.js
js
import { configureStore } from '@reduxjs/toolkit'
// 中间件
// import reduxLogger from 'redux-logger'
import reduxThunk from 'redux-thunk'
// 切片模块
import taskReducer from '../store/features/taskSlice'
// 切片原理
const store = configureStore({
// 指定 reducer
reducer: {
// 按模块管理各个切片导出的reducer
task: taskReducer,
},
// 使用中间件[如果我们不指定任何中间件,则默认集成了ReduxThunk,但是一旦设置,会整体替换默认值,需要手动指定thunk中间件]
middleware: [reduxThunk],
})
export default store
切片文件=>taskReducer
js
import { createSlice } from '@reduxjs/toolkit'
const taskSlice = createSlice({
// 设置切片的名字
name: 'task',
// 设置次切片对应reducer中的初始状态
initialState: {
taskList: [],
count: 0,
},
// 编写业务代码处
reducers: {
setCount(state, action) {
// state:redux中公共状态信息.基于immer库,不需要自己克隆
// action: 派发的行为对象,我们无需考虑行为标识,传递的其他信息,都是以action.payload的方式传递进来的值
state.count = action.payload
},
setTaskList(state, action) {
state.taskList = action.payload
},
},
})
// 利用promise 写一个异步的函数方法,返回一个数组
export function getTaskList() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3])
}, 1000)
})
}
// 从切片中获取actionCreator:此处结构的方法和上线reducers中的方法,仅仅是函数名相同;执行方法,返回需要派发的行为对象,后期我们可以基于dispatch进行任务派发即可!!
export let { setCount, setTaskList } = taskSlice.actions
console.log(setCount([])) // {"type": "task/setCount", "payload": []}
// 实现异步派发[redux-thunk]
export const getTaskListAsync = () => {
return async (dispatch) => {
let res = await getTaskList()
// 注意派发时,需要使用 setTaskList
dispatch(setTaskList(res))
}
}
export default taskSlice.reducer
4. 入口注册store
main.js
js
// 导入store
import store from './store'
import { Provider } from 'react-redux'
import Demo from './views/Demo'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<React.StrictMode>
<Provider store={store}>
<Demo />
</Provider>
</React.StrictMode>
)
5. 获取redux公共状态和派发的方法
获取公共状态 useSelector
其中 taskList, count 就是在task切片中定义的状态
js
const { taskList, count } = useSelector((state) => state.task)
获取派发的事件 useDispatch
js
const dispatch = useDispatch()
dispatch(setTaskList(res)) dispatch中的内容相当于 action.payload

6. extraReducers 用于处理其他切片中的action
使用场景:一个事件中,需要修改两处切片中的值,可以通过例如Aaction让A以及B进行状态的修改
例如登出功能
AutoSlice.js
这里需要删除name字段
js
import { createSlice } from '@reduxjs/toolkit'
const logoSlice = createSlice({
name: 'logo',
initialState: {
name: 'logo',
},
reducers: {
delName(state, action) {
state.name = ''
},
},
})
export default logoSlice.reducer
export const { delName } = logoSlice.actions
TaskSlice.js
这里需要删除userInfo字段
js
import { delName } from './AuthSlice'
// extraReducers 用于处理其他切片中的action
extraReducers: (builder) => {
builder.addCase(delName, (state, action) => {
state.userInfo = {}
})
此时在组件中调用delName的派发事件
即可删除name 以及userInfo
js
import { delName } from '../store/features/AuthSlice'
const handleLogoOut = () => {
dispatch(delName())
}
7. 完整demo案例
- store/index
js
import { configureStore } from '@reduxjs/toolkit'
// 中间
// import reduxLogger from 'redux-logger'
import reduxThunk from 'redux-thunk'
// 切片模块
import taskReducer from '../store/features/taskSlice'
import logoReducer from '../store/features/AuthSlice'
// 切片原理
const store = configureStore({
// 指定 reducer
reducer: {
// 按模块管理各个切片导出的reducer
task: taskReducer,
logo: logoReducer,
},
// 使用中间件[如果我们不指定任何中间件,则默认集成了ReduxThunk,但是一旦设置,会整体替换默认值,需要手动指定thunk中间件]
middleware: [reduxThunk],
})
export default store
- features/AuthSlice
js
import { createSlice } from '@reduxjs/toolkit'
const logoSlice = createSlice({
name: 'logo',
initialState: {
name: 'logo',
},
reducers: {
delName(state, action) {
state.name = ''
},
},
})
export default logoSlice.reducer
export const { delName } = logoSlice.actions
- taskSlice
js
import { createSlice } from '@reduxjs/toolkit'
import { delName } from './AuthSlice'
const taskSlice = createSlice({
// 设置切片的名字
name: 'task',
// 设置次切片对应reducer中的初始状态
initialState: {
taskList: [],
count: 0,
userInfo: {
name: 'zs',
age: 20,
},
},
// 编写业务
reducers: {
setCount(state, action) {
console.log(action)
// state:redux中公共状态信息.基于immer库,不需要自己克隆
// action: 派发的行为对象,我们无需考虑行为标识,传递的其他信息,都是以action.payload的方式传递进来的值
state.count = action.payload
},
setTaskList(state, action) {
state.taskList = action.payload
},
setUserInfo(state, action) {
state.userInfo = action.payload
},
},
// extraReducers 用于处理其他切片中的action
extraReducers: (builder) => {
builder.addCase(delName, (state, action) => {
state.userInfo = {}
})
},
})
// 利用promise 写一个异步的函数方法,返回一个数组
export function getTaskList() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3])
}, 1000)
})
}
// 从切片中获取actionCreator:此处结构的方法和上线reducers中的方法,仅仅是函数名相同;执行方法,返回需要派发的行为对象,后期我们可以基于dispatch进行任务派发即可!!
export let { setCount, setTaskList } = taskSlice.actions
console.log(setCount([])) // {"type": "task/setCount", "payload": []}
// 实现异步派发[redux-thunk]
export const getTaskListAsync = () => {
return async (dispatch) => {
let res = await getTaskList()
// 注意派发时,需要使用 setTaskList
dispatch(setTaskList(res))
}
}
export default taskSlice.reducer
- 项目入口
js
// 导入store
import store from './store'
import { Provider } from 'react-redux'
import Demo from './views/Demo'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<React.StrictMode>
<Provider store={store}>
<Demo />
</Provider>
</React.StrictMode>
)
- 在某个组件中使用
js
import { useDispatch, useSelector } from 'react-redux'
import {
setCount,
getTaskListAsync,
getTaskList,
setTaskList,
} from '../store/features/taskSlice'
import { useEffect } from 'react'
import { delName } from '../store/features/AuthSlice'
const Demo = () => {
/* 获取redux公共状态和派发的方法 */
const { taskList, count, userInfo } = useSelector((state) => state.task)
const { name } = useSelector((state) => state.logo)
const dispatch = useDispatch()
const getData = async () => {
const res = await getTaskList()
dispatch(setTaskList(res))
}
useEffect(() => {
// dispatch(getTaskListAsync())
getData()
}, [])
const handleClick = () => {
dispatch(setCount(count + 1))
}
const handleLogoOut = () => {
dispatch(delName())
}
return (
<div>
123 - {count} - {JSON.stringify(taskList)} - {JSON.stringify(userInfo)} -{' '}
{name}
<br />
<button onClick={handleClick}>add</button>
<br />
<button onClick={handleLogoOut}>logoOut</button>
</div>
)
}
export default Demo