看这篇文章之前,请先阅读《Redux的介绍以及使用(内附完整代码)》这篇文章的内容!!
简介
Redux还为我们提供了一种使用Redux的方式——Redux Toolkit,Redux工具包,简称RTK。RTK可以帮助我们处理使用Redux过程中的重复性工作,简化Redux中的各种操作。
安装
无论是RTK还是Redux,在React中使用时react-redux都是必不可少,所以使用RTK依然需要安装两个包:react-redux和@reduxjs/toolkit。
npm install react-redux @reduxjs/toolkit -S
configureStore
使用RTK时,reducer依然可以使用之前的创建方式不变,但是不在需要合并reducer。RTK为我们提供了一个configureStore方法,它直接接收一个对象作为参数,可以将reducer的相关配置直接通过该对象传递,而不再需要单独合并reducer。
之前redux那一小节是使用的是combineReducers和createStore
const reducers = combineReducers({
pageAReducer,
pageBReducer
})
const store = configureStore(reducers)
修改为
const reducers = {
reducer: {
pageAReducer,
pageBReducer
}
}
const store = configureStore(reducers)
configureStore需要一个对象作为参数,在这个对象中可以通过不同的属性来对store进行设置,比如:reducer属性用来设置store中关联到的reducer,preloadedState用来指定state的初始值等。
reducer属性可以直接传递一个reducer,也可以传递一个对象作为值。如果只传递一个reducer,则意味着store中只有一个reducer。若传递一个对象作为参数,对象的每个属性都可以执行一个reducer,在方法内部它会自动对这些reducer进行合并。
CreateSlice
createSlice是一个全自动的创建reducer切片的方法,在它的内部调用就是createAction和createReducer,之所以先介绍那两个也是这个原因。createSlice需要一个对象作为参数,对象中通过不同的属性来指定reducer的配置信息。
createSlice(configuration object)
配置对象中的属性:
initialState —— state的初始值
name —— reducer的名字,会作为action中type属性的前缀,不要重复
reducers —— reducer的具体方法,需要一个对象作为参数,可以以方法的形式添加reducer,RTK会自动生成action对象。
例如创建pageASlice
const pageASlice = createSlice({
name: 'pageAReducer',
initialState: {
num: 20
},
reducers: {
setAddNum(state, action) {
state.num = state.num + action.payload
},
setSubNum(state, action) {
state.num = state.num - action.payload
}
}
})
createSlice返回的并不是一个reducer对象而是一个slice对象(切片对象)。这个对象中我们需要使用的属性现在有两个一个叫做actions,一个叫做reducer。
Actions
切片对象会根据我们对象中的reducers方法来自动创建action对象,这些action对象会存储到切片对象actions属性中:
console.log(pageASlice.actions);
打印结果
actions中的方法,可以通过解构赋值获取到切片中的action。开发中可以将这些取出的action对象作为组件向外部导出,导出其他组件就可以直接导入这些action,然后即可通过action来触发reducer。
export const { setAddNum, setSubNum } = pageASlice.actions
Reducer
切片的reducer属性是切片根据我们传递的方法自动创建生成的reducer,需要将其作为reducer传递进configureStore的配置对象中以使其生效:
export const { reducer: pageAReducer } = pageASlice
const store = configureStore({
reducer: {
pageAReducer
}
})
完整代码示例
我们现在利用RTK来改造《Redux的介绍以及使用(内附完整代码)》这节的内容
目录结构
components
src\components\PageA.jsx
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { setAddNum, setSubNum } from '../store/slice/PageA/pageASlice'
export default function () {
const pagea = useSelector(state => {
return state.pageAReducer
})
const dispatch = useDispatch()
const onClickOne = () => {
dispatch(setAddNum(1))
}
const onClickTwo = () => {
dispatch(setSubNum(2))
}
return (
<div>
<button onClick={onClickOne}>增加</button>
<p>{pagea.num}</p>
<button onClick={onClickTwo}>减少</button>
</div>
)
}
src\components\PageB.jsx
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { setPushNum } from '../store/slice/PageB/pageBSlice'
export default function PageB() {
const dispatch = useDispatch();
const pageb = useSelector(state => state.pageBReducer)
const onClick = () => {
dispatch(setPushNum(50))
}
return (
<div>
<button onClick={onClick}>变化</button>
<p>{pageb.arr.join(" ")}</p>
</div>
)
}
slice
src\store\slice\PageA\pageASlice.jsx
import { createSlice } from "@reduxjs/toolkit"
const pageASlice = createSlice({
name: 'pageAReducer',
initialState: {
num: 20
},
reducers: {
setAddNum(state, action) {
state.num = state.num + action.payload
},
setSubNum(state, action) {
state.num = state.num - action.payload
}
}
})
export const { setAddNum, setSubNum } = pageASlice.actions
export const { reducer: pageAReducer } = pageASlice
src\store\slice\PageB\pageBSlice.jsx
import { createSlice } from "@reduxjs/toolkit";
const pageBSlice = createSlice({
name: 'pageBReducer',
initialState: {
arr: [10, 20, 30]
},
reducers: {
setPushNum(state, action) {
state.arr.push(action.payload)
}
}
})
export const { setPushNum } = pageBSlice.actions
export const { reducer: pageBReducer } = pageBSlice
store
src\store\index.jsx
import { configureStore } from "@reduxjs/toolkit";
import { pageAReducer } from './slice/PageA/pageASlice'
import { pageBReducer } from './slice/PageB/pageBSlice'
const store = configureStore({
reducer: {
pageAReducer,
pageBReducer
}
})
export default store