• React redux、react-redux的基本使用(笔记)


    1. redux 是什么

    • redux 是一个专门用于做状态管理的 JS 库 (不是 react 插件库)
    • 它可以用在各种项目中,但是基本与 react 配合使用
    • 作用:集中式管理 react 应用中多个组件共享的状态

    2. 什么时候使用 redux

    • 多个组件依赖于同一状态
    • 多个组件所依赖的数据都是相互影响的,组件 A 中共享数据的更改,组件 B 中共享的同一数据默认也会改

    3. redux 安装与使用

    3.1 安装

    // 使用 npm 安装
    npm i redux
    
    • 1
    • 2

    3.2 完整使用

    • 创建 redux/store.js 文件,存放数据

      // 用于创建一个 store
      import { createStore } from "redux"
      // 用于 Count 组件服务的 reducer
      import countReducer from "./count_reducer.js"
      
      export default createStore(countReducer)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 创建 redux/count_reducer.js 文件,处理数据

      import { ADD, SUB } from "./constant.js"
      
      // preState:表示初始值,或前一次状态的值
      export default function countReducer(preState = 0, action){
        // action:它是一个对象,包含了方法和数据
        let { type, data } = action
        switch(type) {
          case ADD:
        	  return preState + data
          case SUB:
        	  return preState - data
          default:
            return preState
           // 必须要返回一个新值或初始值
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • 创建 redux/count_action.js 文件,提供方法

      import { ADD, SUB } from "./constant.js"
      
      // action 需要返回一个对象,type:方法名、data:数据
      export const addAction = data => ({ type: ADD, data })
      export const subAction = data => ({ type: SUB, data })
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 创建 redux/constant.js 文件,命名空间

      // 因为 type 方法名称在多处都会使用到,这样写便于管理,还可以防止程序员写错
      export const ADD = "add"
      export const SUB = "sub"
      
      • 1
      • 2
      • 3
    • 组件中使用 store

      import { Component } from "react";
      import store from "./src/redux/store.js"
      import { addAction, subAction } from "./src/redux/count_action.js"
      
      export default class Count extends Component {
        componentDidMount() {
          /*
            store 中的值发生了改变,并不会调用自动 render
            当 store 中的值发生了改变,store.subscribe 会触发回调,然后使用 this.setState 强制调用 render
            这样写有一点不好,就是每在一个组件使用一次,都需要再去写一遍,可以直接在入口文件中使用
            这样只要有一个组件中的 redux 值发生了改变,就会更新视图
            store.subscribe(() => {
              ReactDOM.render(, document.getElement("root"))
            })
          */
          store.subscribe(() => {
            this.setState({})
          })
        }
       
        add = (data) => {
          // dispatch 会触发 reducer 函数(这里指 countReducer 函数)
          store.dispatch(addAction(data))
        }
      
        sub = (data) => {
          store.dispatch(subAction(data))
        }
      
        render() {
          return (
            // getState 使用数据,store 本身是一个对象
            <div>{ store.getState() }</div>
          )
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36

    3.3 异步 action

    // 当 action 为函数时,它将会成为一个异步 action
    
    import { createStore, applyMiddleware } from "redux"
    // 引入 redux-thunk,用于支持异步 action
    import thunk from "redux-thunk"
    
    // 此时暴露时,需要执行中间件
    export default createStore(countReducer, applyMiddleware(thunk))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    // 这个时候写 action 时,就可以返回函数了
    // 异步函数里面还是调用的同步函数
    export const addAsyncAction = (data, time) => {
      return (dispath) => {
        setTimeout(() => {
          dispath(addAction(data))
        },time)
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    store.dispatch(addAsyncAction(data, 300))
    
    • 1

    4. react-redux 的理解

    • react-redux 是对 redux 的封装,成为了 react 的一个插件库
    • react-redux 中所有的容器组件都应该包裹一个UI组件,他们为父子关系
    • 只有容器组件才能调用 react-redux 中的方法,store.getState()、store.dispath(action)
    • UI组件的状态和方法,只能通过 props 传递

    5. react-redux 安装与使用

    5.1 安装

    npm i react-redux
    
    • 1

    5.2 连接容器组件和UI组件

    • 容器组件,连接容器组件和UI组件

      // count 容器组件,容器组件要写在 container 文件下,UI组件要写在 component 文件下
      import CountUI from "./component/Count"
      // 用于连接 UI 和 store,但此时只连接了 UI
      import { connect } from "react-redux"
      
      export default connect()(CountUI) // 有了 connect 函数不需要在手动检测数据的变化了
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 引入容器组件,连接容器组件和 store

      // 使用组件时,要使用容器组件
      import Count from "./container/Count"
      // 使用时需要把 store 作为 prop 值传过去
      import store from "./redux/store"
      
      export default class Demo extends Componet {
        render(){
          return <Count store={store}></Count>
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    • UI组件

      // 正常写页面就可以了
      
      • 1

    5.3 基本使用

    // 容器组件
    import { connect } from "react-redux"
    
    import CountUI from "../component/Count"
    import { addAction } from "../redux/count_action"
    
    // 该函数返回一个存状态的对象,会把该对象的值映射到 CountUI 组件的 props 中
    function mapStateToProps(state){
      return {
        // state ==> store.getState()
        count: state
      }
    }
    // 该函数返回一个存方法的对象,映射到 props 中
    function mapDispatchToProps(dispatch){
      return {
        // dispatch ==> store.dispath
        add: (data) => {
          dispatch(addAction(data))
        }
      }
    }
    
    // 此时连接了 UI 和 store
    export default connect(mapStateToProps, mapStateToProps)(CountUI)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    // UI组件
    export default class CountUI extends Componet {
      return(){
        console.log(this.porps) // {store: {…}, count: 0, add: ƒ},这里也可以拿到 store 对象
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    6. react-redux 优化

    6.1 简写 mapDispatchToProps

    // 优化前
    import { connect } from "react-redux";
    
    import countUI from "../components/CountUI.jsx";
    import { addAction, subAction, addAsyncAction } from "../redux/count_action";
    
    export default connect(
      (state) => ({
        count: state,
      }),
      // 当 mapDispatchToProps 为对象时,可以直接把函数赋值过去
      {
        add: addAction,
        sub: subAction,
        addAsync: addAsyncAction,
      }
    )(countUI);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    6.2 使用 Provider 组件

    import React from "react";
    import reactDOM from "react-dom";
    import { Provider } from "react-redux";
    
    import store from "./redux/store";
    import App from "./App.jsx";
    
    // 在这里使用 Provider 组件传入 store 值,使后续的所有组件都不需要再次传入 store
    reactDOM.render(
        <Provider store={store}>
            <App />
        </Provider>,
        document.getElementById("root")
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    6.3 合并UI组件和容器组件

    import React, { Component } from "react";
    import { connect } from "react-redux";
    
    import { addAction, subAction, addAsyncAction } from "../redux/count_action";
    
    // UI组件部分
    class countUI extends Component {
      add = () => {
        let { value } = this.selectNode;
        this.props.add(Number(value));
      };
    
      sub = () => {
        let { value } = this.selectNode;
        this.props.sub(Number(value));
      };
    
      addAsync = () => {
        let { value } = this.selectNode;
        this.props.addAsync(Number(value), 500);
      };
      render() {
        let { count } = this.props;
        return (
          <div>
            <div>
              <h1>{count}</h1>
              <select ref={(curNode) => (this.selectNode = curNode)}>
                <option>1</option>
                <option>2</option>
                <option>3</option>
              </select>
              <button onClick={this.add}>点我加</button>
              <button onClick={this.sub}>点我减</button>
              <button onClick={this.addAsync}>异步加</button>
            </div>
          </div>
        );
      }
    }
    
    // connect 连接部分
    export default connect (
      (state) => ({
        count: state,
      }),
      {
        add: addAction,
        sub: subAction,
        addAsync: addAsyncAction,
      }
    )(countUI);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    7. 数据共享

    7.1 文件结构

    |-- redux 				// 数据处理的总文件夹
      |-- reducers			// 集中管理reducer
    	|-- demo1.js		// 第一个reducer
    	|-- demo2.js		// 第二...
    	|-- index.js		// reducers的汇总
      |-- actions			// 集中管理action
    	|-- demo1.js		// 第一个action
    	|-- demo2.js		// 第二...
      |-- constant.js		// 命名空间
      |-- sotre.js			// 主文件,存放状态
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    家庭宽带qos服务级别及服务器跑家宽
    【Rust中的struct】
    00_linux_最简单构建字符设备 2.4版本之前使用
    知物由学 | “群控软件”助长黑灰产套利的零和游戏,硬核技术打击隐秘的不公
    第十三届蓝桥杯 C++ B 组省赛 F 题——统计子矩阵 (AC)
    vue 聊天页面
    Google出品的NotebookLM 人工智能笔记本,一款基于RAG的personalized AI产品
    大模型在数据分析场景下的能力评测
    长沙驾考之路
    MySQL之函数
  • 原文地址:https://blog.csdn.net/weixin_60547084/article/details/125998899