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

 

posted @ 2023-02-13 15:32  艾尔夏尔-Layton  阅读(30)  评论(0编辑  收藏  举报