leiwuhen-67's blog leiwuhen-67's blog
首页
    • 《Vue》笔记
    • 《React》笔记
    • 《NodeJs》笔记
    • 《CSS》笔记
    • 《Redis》笔记
    • 基础入门
    • 《Mock》笔记
    • 《MySQL》笔记
    • 《Git》相关
影音视听
收藏
关于
GitHub (opens new window)

我的公众号

首页
    • 《Vue》笔记
    • 《React》笔记
    • 《NodeJs》笔记
    • 《CSS》笔记
    • 《Redis》笔记
    • 基础入门
    • 《Mock》笔记
    • 《MySQL》笔记
    • 《Git》相关
影音视听
收藏
关于
GitHub (opens new window)
  • React

    • 使用React脚手架快速搭建项目
    • hooks之useEffect
    • React之事件绑定及简写方式
    • React之props传值并对其进行限制
    • React之Refs的基本使用
    • React之生命周期钩子
    • React之key的使用
    • React之代理服务器配置
    • React之封装全局Loading组件
    • React之消息的发布-订阅(pubsub-js)
    • React之Redux的基本使用
      • React之react-redux的基本使用
      • React之redux的数据持久化存储
      • React之路由懒加载
      • React之Render Props的使用
      • React之createBrowserRouter
      • React之路径别名@配置
      • React之craco打包优化配置
      • React之项目国际化
      • React之postcss-pxtorem移动端适配
      • React之使用vite创建项目
      • React之ts类型标注汇总
      • React之使用 ant design搭建后台管理之踩坑
      • React之路由切换动画
      • React之使用vite创建组件库并发布到npm
      • React之项目打包部署到nginx
      • React之自定义组件添加className与style
    • React Native

    • 《React》笔记
    • React
    心欲无痕
    2024-03-19
    目录

    React之Redux的基本使用

    在项目中有这样的使用场景,就是多个组件需要共享同一个状态,或者其他组件想要更改某个组件里的状态,如果用组件传值跟消息发布 - 订阅虽然也能实现,但是实现起来却很繁琐,因此这时候就需要使用到 Redux 了,它是一个状态管理容器,帮助我们集中管理状态。

    Redux 三要素:

    • actions:js 普通对象,必须含有一个字符串类型的 type 字段表示将要执行的动作。
    • store:维持应用的 state,提供 getState () 方法获取 state;通过 dispatch (action) 更新 state,通过 subscribe (listener) 注册监听器,通过 subscribe (listener) 返回的函数注销监听器。Redux 应用只有一个单一的 store
    • reducers:纯函数,接收先前的 state 和 action,并返回新的 state

    原理图:

    现在就用一个加减运算的案例来说明 redux 如何使用。

    # redux 使用

    # 1、安装 Redux

    npm install redux
    
    1

    # 2、编写 store 和 reducer 文件

    在项目根目录的 src 文件夹下创建 redux 文件夹,在该文件夹下创建 store.js 文件和 countReducer.js 文件

    // src/redux/countReducer.js
    const initialState = 0
    const countReducer = (state = initialState, action) => {
      switch (action.type) {
        case 'ADD':
          return state + 1
        case 'MINUS':
          return state - 1
        default:
          return state
      }
    }
    
    export default countReducer
    
    
    // src/redux/store.js
    import { createStore } from "redux"
    import countReducer from "./countReducer";
    
    export default createStore(countReducer)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    # 3、创建组件 Count.jsx

    // class组件实现
    import React, { Component } from 'react';
    import store from "../../redux/store";
    
    class Count extends Component {
        state = {
            count: store.getState()
        }
        // 加运算
        handleAdd = () => {
            store.dispatch({type: "ADD"})
        }
        // 减运算
        handleReduce = () => {
            store.dispatch({type: "MINUS"})
        }
        // 组件挂载时,监听store改变时,更新状态
        componentDidMount() {
            this.storeSubscribe = store.subscribe(() => {
                this.setState({
                    count: store.getState()
                })
            })
        }
        // 组件卸载时取消监听
        componentWillUnmount() {
            this.storeSubscribe()
        }
    
        render() {
            return (
                <div>
                   <h3>当前结果:{this.state.count}</h3>
                    <button onClick={ () => this.handleAdd() }>加1</button>
                    <button onClick={ () => this.handleReduce() }>减1</button>
                </div>
            );
        }
    }
    
    export default Count;
    
    
    
    // function组件实现
    import React, { useState, useEffect } from 'react';
    import store from "../../redux/store";
    
    const Count = () => {
        const [count, setCount] = useState(store.getState());
        useEffect(() => {
            const unsubscribe = store.subscribe(() => {
                setCount(store.getState())
            })
            return () => {
                unsubscribe()
            }
        }, [count])
        const handleAdd = () => {
            store.dispatch({type: "ADD"})
        }
        const handleReduce = () => {
            store.dispatch({type: "MINUS"})
        }
        return (
            <div>
               <h3>当前结果:{count}</h3>
               <button onClick={ () => handleAdd() }>加1</button>
               <button onClick={ () => handleReduce() }>减1</button>
            </div>
        );
    };
    
    export default Count;
    
    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74

    当应用越来越复杂时,我们可以将 reducer 函数拆分成多个单独的函数,拆分后的函数负责独立管理 state 的一部分,这里需要用到 combineReducers 辅助函数,它的作用是把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore 方法。

    例如,现在还有一个管理用户信息的 reducer,

    const initialState = {
        name: "张三",
        age: 28
    }
    
    const userReducer = (state = initialState, action) => {
      switch (action.type) {
        case "changeAge":
          return {
              ...state,
              age: action.payload
          }
        default:
          return state
      }
    }
    export default userReducer
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    那么 src/redux/store.js 文件则更改如下:

    import { createStore, combineReducers } from "redux"
    import countReducer from "./countReducer";
    import userReducer from "./userReducer";
    
    const reducer = combineReducers({
      countReducer,
      userReducer
    })
    export default createStore(reducer)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    此时,在 Count.jsx 组件中使用如下:

    import React, {useState, useEffect} from 'react';
    import store from "../../redux/store";
    
    const Count = () => {
        const [count, setCount] = useState(store.getState().countReducer);
        const [user, setUser] = useState(store.getState().userReducer);
        useEffect(() => {
            const unsubscribe = store.subscribe(() => {
                setCount(store.getState().countReducer)
                setUser(store.getState().userReducer)
            })
            return () => {
                unsubscribe()
            }
        }, [count, user])
        const handleAdd = () => {
            store.dispatch({type: "ADD"})
        }
        const handleReduce = () => {
            store.dispatch({type: "MINUS"})
        }
        const changeAge = () => {
            store.dispatch({type: "changeAge", payload: 100})
        }
        return (
            <div>
               <h3>当前结果:{count}</h3>
                <h3>用户信息:姓名:{user.name},年龄:{user.age}</h3>
               <button onClick={ () => handleAdd() }>加1</button>
               <button onClick={ () => handleReduce() }>减1</button>
               <button onClick={ () => changeAge() }>更改年龄</button>
            </div>
        );
    };
    
    export default Count;
    
    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
    编辑 (opens new window)
    上次更新: 7/1/2024, 4:56:33 PM
    React之消息的发布-订阅(pubsub-js)
    React之react-redux的基本使用

    ← React之消息的发布-订阅(pubsub-js) React之react-redux的基本使用→

    Theme by Vdoing
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式