📄目录结构
- Redux是什么?
- 什么时候用Redux?
- 如何使用react-redux?
- Redux术语
- 如何使用redux toolkit?
🔖Demo
| 标题 | Demo |
|---|---|
| react-redux | Demo |
| redux toolkit | Demo |
Redux是什么?
它是状态管理层的解决方案,状态是什么?简单来说就是react当中的state。随着逻辑越来越复杂,我们就需要去引入专门的一层来去做状态管理相关的事情,redux就是这样的一层。
我们先来看一个简单的计数器组件:
function Counter() {
// State:计数器值
const [counter, setCounter] = useState(0);
// Action:当发生某一操作时,更新状态
const increment = () => {
setCounter(prevCounter => prevCounter + 1)
}
// View: UI定义
return (
<div>
value: {counter}
<button onClick={increment}>Increment</button>
</div>
)
}
这个计数器组件可以分为三个阶段:
第一个阶段是我们在组件里面定义了一个计数器状态;接着我们用这个计数器状态去定义视图层的UI结构、UI内容;当我们点击视图层的按钮,可以触发这个状态的更新,也就是Action。
所以这三个阶段是:
- State:计数器值
- Action:当发生某一操作时,更新状态。
- View:UI定义。
什么时候用Redux?
只有应用复杂到一定程度的时候,redux才会给我们带来收益,否则只会增加我们整个应用的复杂度。
这里提到了两个问题:
- 假设B2-B3存在共享的状态,那应该怎么做呢?
- 那如果B2-A2这两个组件有需要共享的组件应该怎么办呢?
对于问题1,有专门的解决方案,叫做状态提升。就是把B2和B3公用的
state提升到B1这个层级。
也就是B1这个组件去管理公用的state,然后B1组件通过props传递给B2、B3,这样B2、B3都可以去使用B1这个state,这其实就是一个状态提升。
对于问题2,我们是按照状态提升的原则,将A1、B2的共有状态提升到A1,然后再由A1经过B1返给B2,这个时候我们通过状态提升去解决状态共享就有一些麻烦了。
当组件树的层级越复杂然后要共享的节点之间离得越远,层级差异度越大,这个通过状态提升解决的问题复杂度也会越高。
这时候通过redux引入一个全局的状态管理,可以让任意层级的组件在需要使用相关状态的时候直接从redux当中去获取就可以了。
避免了需要一层层的组件传递的问题。
如何使用react-redux?
我们以实现一个计算器为例:
当我们在页面按下“加数”,看到的是0变成2的结果。实际上,内部的过程是通过onClick事件调用方法去执行。
onClick里的addAmount方法会返回action,dispatch把action传给reducer。reducer根据action里的type进行判断并返回计算结果,页面更新state。
这就是在页面上由0增加为2的整个过程。
实现逻辑被我抽象成了下图:
作为练手的入门小项目,我的src目录如下,
| -index.js入口文件
| - App.js 入口组件
| - Counter.js 计算器组件
| - store.js 整个项目唯一的保存数据的地方,可以当做容器
| - reducer.js 接收action并且帮助store生成state的计算过程
| - actions.js 用户在网页上触发的操作
| - styles.css 样式文件
// index.js
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { store } from "./store";
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
,
rootElement
);
在入口就通过Provider提供store,这样即使后面有再多的组件,都可以通过useSelector取到state。
Redux术语
import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({ reducer: counterReducer })
console.log(store.getState())
reduxjs/toolkit就是基于Redux的上层封装库,reduxtoolkit,简称RTK。
通过这个库来使用redux来变得更加简洁。
我们导入RTK库里的configureStore就可以创建出来store,configure当中传入的是一个reducer的一个对象。
再通过getState保存的方法,我们就能拿到这个store当中保存的状态。
如何使用redux toolkit?
我们通过增减计数例子来学习:
目录结构按照官方文档提供的来:
- app
- store.js
- features
- counter
- Counter.js
- counterSlice.js
- counter
- App.js
- index.js
- styles.css
特别值得注意的是它比react-redux多了一个叫counterSlice的文件,所以我们重点放在它上面。
// counterSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
value: 0
};
export const counterSlice = createSlice({
name:"counter",
initialState,
reducers: {
increment: (state) => {
// Redux Toolkit 允许我们在reducer中编写“变异(mutating)”逻辑。
// state.value+=1 它实际上并不改变状态,是纯函数。
// 因为它使用Timmer库,它检测‘draft状态’的变化
// 并基于这些变化产生一个全新的不可变状态
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
}
}
});