Redux是基于React的一个统一状态管理库。可以更容易实现组件间的状态共享问题,同时可以通过React DevTools工具记录并调试。
npm i redux @reduxjs/toolkit;
src
文件夹创建名为store
文件夹,并在里边新增一个index
模块。index
模块中定义store实例,并默认导出react-redux
中引入Provider
组件,通过该组件将store注入进去combineReducers
函数合并成一个大的reducer函数。每一个reducer函数接收两个参数
现在React已经进入Hook时代,因此 可以通过
useSelector hook
来从整个状态对象选出您所需的状态。
let selected = useSelector(selector)
Redux中修改状态的唯一方式:dipatch一个action对象。reducer函数在执行时根据不同的action.type完成状态修改 并 返回新状态。
通过 react-redux库中的useDispath hook
来获取 到 dispath 函数。在调用时传入一个action对象即可完成状态修改.
const dispatch = useDispatch()
dispatch({type: '', payload: 10})
在 RTK 包中引入createSlice
函数来创建一个slice对象。
const slice = createSlice(options)
其中options对象包含以下常用属性
name:给action对象的type属性指定命名空间
initialState:指定状态的初始值
reducers:在该对象中定义各种修改状态的reducer函数
slice中reducer函数都可以直接通过state修改状态,无需在返回新状态
import { createSlice } from '@reduxjs/toolkit';
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
addOne(state) {
state.value++;
},
},
});
//! counterSlice.actions对象包含所有与reducers函数同步的action对象creator函数
export const { addOne } = counterSlice.actions;
// counterSlice.reducer 就是 最终counter状态的修改函数
export default counterSlice.reducer;
## 4. 异步处理
Redux原生不支持异步处理机制,需要我们通过一些中间件去完成。
好在,Redux Toolkit中内置了Thunk中间件可以完成异步任务处理。因此 在UI组件中调用dispatch时,不仅可以传入一个Action对象,还可以传入一个thunk
函数,由其处理异步任务有结果后,在dispatch
一个action去修改状态。
那么,什么是Thunk函数?
getState 用来获取完整的store中的状态对象,以备之需
//! 实现异步处理
//* 通过定义一个thunk函数 去完成异步任务即可
export function asyncAddOne(dispatch, getState) {
//* getState调用后返回整个store中的状态对象,而不是某个slice下的状态
let state = getState();
console.log(state);
// 异步任务
setTimeout(() => {
dispatch(addOne());
}, 1000);
}
Counter组件中,
import Styles from './counter.module.css';
import { useSelector, useDispatch } from 'react-redux';
// 引入Thunk函数
import { asyncAddOne } from './counterSlice';
function Counter() {
const dispatch = useDispatch();
let count = useSelector(({ counter }) => counter.value);
return (
<div className={Styles.counter}>
<p>计数:{count}</p>
<p>
<button
onClick={() => {
//! dispatch时传入thunk函数
dispatch(asyncAddOne);
}}
>
aysnc add
</button>
</p>
</div>
);
}
export default Counter;