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
标签:状态,const,ADD,react,ITEM,state,action,return,redux From: https://www.cnblogs.com/CNLayton/p/17115846.html