react状态管理redux
redux产生的历史背景
当我们的前端系统变得复杂,包含众多子组件,特别是包含很长一条子组件链时。我们的state管理就会非常繁琐,例如如下图,如果Child11需要用到App里的state,那么App里的state就要通过props一层层传递下去,尽管Child2到5不需要用到,但props还是要传递。
同时如果Child5和Child7需要进行数据交互,那么他们的state肯定要提升到App里,相似的,App里的state就会非常的庞大且冗杂。

同时这样的设计会造成不必要的渲染,在下图如果我们把Comp1的state更新至Comp4,我们真正想重新渲染的是Comp4,但是Comp2和3也会跟着渲染,这会造成性能的浪费。
redux
react的哲学本质是 UI = f(state),当我们组件的state变得复杂时,就需要redux进行状态管理了。
redux里有三个概念:Action、Store、Reducers,他们三者的结合共同帮助我们CRUDstate里的数据

store
store是一个只读的单一数据源,设计理念和state一致,不能直接改变原有的数据,只能将引用指向新的数据
Reducers
reducers他负责对变化进行分发和处理,最终将新的数据返回给Store,本质是通过不同的action和旧状态state,生产出新状态返回给store
Actions
action是对变化的描述,例如增删改都可以是一种action
redux使用案例
redux的安装
npm install redux react-redux
定义ActionTypes
这里的actiontype是action的类型,本质就是字符串,用于区分不同的action
export const ADD_ITEM = "ADD-ITEM";
export const DELETE_ITEM = "DELETE_ITEM";
定义Reducer
这里的reducer定义了不同action产生的不同state结果,initialState是初始的state状态
import {ADD_ITEM,DELETE_ITEM} from "../actionTypes/actionTypes";
const initialState = { //state的初始状态
numOfItems: 0,
};
export const cartReducer = (state = initialState, action) => {
switch (action.type) { //根据不同的action生成不同的新state
case ADD_ITEM:
return {
numOfItems: state.numOfItems + 1,
};
case DELETE_ITEM:
return {
numOfItems: state.numOfItems - 1,
};
default:
return state;
}
};
定义Actions
这里对action进行了显示封装,注意返回的是一个类,这个类里有type属性,用于区分不同的action
import { ADD_ITEM, DELETE_ITEM } from "../actionTypes/actionTypes";
const addItem = () => {
return {
type: ADD_ITEM,
};
};
const deleteItem = () => {
return {
type: DELETE_ITEM,
};
};
export { addItem, deleteItem };
在组间里调用action
组件是不同直接和store交互的,桥梁是action,通过useDispatch我们可以拿到分发器,然后通过上面我们定义的不同action,产生新的state
import React, {useState} from "react";
import {useDispatch, useSelector} from "react-redux";
import {addItem, deleteItem} from "../actions/cartAction";
const Cart = () => {
const state = useSelector((state) => state); //用于拿到当前的state
const dispatch = useDispatch(); //dispatch用于分发action到reducer里
return (
<div className="cart">
<h2>Number of items in Cart:{state.numOfItems}</h2>
<button onClick={() => {
dispatch(addItem()); //调用addItem函数,用于产生一个action,分发给reducer里影响state
}} className="green">Add Item to Cart
</button>
<button onClick={() => {
dispatch(deleteItem()); //调用deleteItem函数,用于产生一个action,分发给reducer里影响state
}} className="red">Remove Item from Cart
</button>
</div>
);
};
export default Cart;
传递参数
若在action里需要传递参数,则需要这样写
addNumItem里接受num参数,并把它放在payload属性里
import {ADD_ITEM, ADD_NUM_ITEM, DELETE_ITEM} from "../actionTypes/actionTypes";
const addItem = () => {
return {
type: ADD_ITEM,
};
};
const addNumItem = (num) => {
return {
type: ADD_NUM_ITEM,
payload: num
};
};
const deleteItem = () => {
return {
type: DELETE_ITEM,
};
};
export {addItem, deleteItem, addNumItem};
在reducer里我们通过action.payload拿到对应的参数
import {ADD_ITEM, ADD_NUM_ITEM, DELETE_ITEM} from "../actionTypes/actionTypes";
const initialState = { //state的初始状态
numOfItems: 0,
};
export const cartReducer = (state = initialState, action) => {
switch (action.type) { //根据不同的action生成不同的新state
case ADD_ITEM:
return {
numOfItems: state.numOfItems + 1,
};
case DELETE_ITEM:
return {
numOfItems: state.numOfItems - 1,
};
case ADD_NUM_ITEM:
return {
numOfItems: state.numOfItems + action.payload,
};
default:
return state;
}
};
如果有多个参数,我们可以封装成一个类放进payload里
const addNumItem = (id,text) => { return { type: ADD_NUM_ITEM, payload: { id, text } }; };
references
https://juejin.cn/post/6844903842140667911
https://www.freecodecamp.org/news/how-to-build-a-redux-powered-react-app/
https://www.freecodecamp.org/news/what-is-redux-store-actions-reducers-explained/
https://juejin.cn/post/7137966532713267237


浙公网安备 33010602011771号