【前端知识】React 基础巩固(三十二)——Redux的三大原则、使用流程及实践

React 基础巩固(三十二)------Redux的三大原则

一、Redux的三大原则

  1. 单一数据源

    • 整个应用程序的state被存储在一颗object tree 中,并且这个object tree 只存储在一个store中;
    • Redux并没有强制让我们不能创建多个Store,但是那样做不利于数据维护;
    • 单一的数据源可以让整个应用程序的state变得方便维护、追踪、修改;
  2. State是只读的

    • 唯一修改State的方法一定是触发action,不要试图在其他地方通过任何的方式来修改State;

    • 这样就确保了View或网络请求都不能直接修改state,它们只能通过action来描述自己想要如何修改state;

    • 这样可以保证所有的修改都被集中化处理,并且按照严格的顺序来执行,所以不需要担心reace condition(竞态)的问题;

  3. 使用纯函数来执行修改

    • 通过reducer将旧state和actions联系在一起,并且返回一个新的state;
    • 随着应用程序的复杂度增加,我们可以将reducer拆分成多个小的reducers,分别操作不同state tree 的一部分;
    • 但是所有的reducer都应该是纯函数,不能产生任何的副作用;

二、Redux的使用流程

三、Redux的基本使用(计数器小案例)

  1. 构建react项目

    bash 复制代码
    # 创建新的react项目
    create-react-app redux-learn
    # 创建成功后cd进入文件夹,随后安装redux
    npm install redux
  2. 删除暂时无关文件,构建store相关文件,并引用store至所需页面中

    • 目录
  • store/constants.js

    javascript 复制代码
    export const ADD_NUMBER = "add_number";
    export const SUB_NUMBER = "sub_number";
  • store/reducer.js

    javascript 复制代码
    import * as actionTypes from "./constants";
    
    const initialState = {
      counter: 111,
    };
    
    function reducer(state = initialState, action) {
      switch (action.type) {
        case actionTypes.ADD_NUMBER:
          return { ...state, counter: state.counter + action.num };
        case actionTypes.SUB_NUMBER:
          return { ...state, counter: state.counter - action.num };
        default:
          return state;
      }
    }
    
    export default reducer;
  • store/actionCreators.js

    javascript 复制代码
    import * as actionTypes from "./constants";
    
    export const addNumberAction = (num) => ({
      type: actionTypes.ADD_NUMBER,
      num,
    });
    
    export const subNumberAction = (num) => ({
      type: actionTypes.SUB_NUMBER,
      num,
    });
  • store/index.js

    javascript 复制代码
    import { createStore } from "redux";
    import reducer from "./reducer";
    
    const store = createStore(reducer);
    
    export default store;
  • pages/home.jsx

    javascript 复制代码
    import React, { PureComponent } from "react";
    import store from "../store";
    import { addNumberAction } from "../store/actionCreators";
    export class home extends PureComponent {
      constructor() {
        super();
    
        this.state = {
          counter: store.getState().counter,
        };
      }
      componentDidMount() {
        store.subscribe(() => {
          const state = store.getState();
          this.setState({
            counter: state.counter,
          });
        });
      }
    
      addNumber(num) {
        store.dispatch(addNumberAction(num));
      }
    
      render() {
        const { counter } = this.state;
        return (
          <div>
            home counter:{counter}
            <div>
              <button onClick={(e) => this.addNumber(1)}>+1</button>
              <button onClick={(e) => this.addNumber(5)}>+5</button>
              <button onClick={(e) => this.addNumber(8)}>+8</button>
            </div>
          </div>
        );
      }
    }
    
    export default home;
  • pages/profile.jsx

    javascript 复制代码
    import React, { PureComponent } from "react";
    import store from "../store";
    import { subNumberAction } from "../store/actionCreators";
    export class profile extends PureComponent {
      constructor() {
        super();
    
        this.state = {
          counter: store.getState().counter,
        };
      }
      componentDidMount() {
        store.subscribe(() => {
          const state = store.getState();
          this.setState({
            counter: state.counter,
          });
        });
      }
    
      subNumber(num) {
        store.dispatch(subNumberAction(num));
      }
    
      render() {
        const { counter } = this.state;
        return (
          <div>
            profile counter:{counter}
            <div>
              <button onClick={(e) => this.subNumber(1)}>-1</button>
              <button onClick={(e) => this.subNumber(5)}>-5</button>
              <button onClick={(e) => this.subNumber(8)}>-8</button>
            </div>
          </div>
        );
      }
    }
    
    export default profile;
  • App.jsx

    javascript 复制代码
    import React, { PureComponent } from "react";
    import Home from "./pages/home";
    import Profile from "./pages/profile";
    import "./style.css";
    import store from "./store";
    
    export class App extends PureComponent {
      constructor() {
        super();
    
        this.state = {
          counter: store.getState().counter,
        };
      }
      componentDidMount() {
        store.subscribe(() => {
          const state = store.getState();
          this.setState({
            counter: state.counter,
          });
        });
      }
      render() {
        const { counter } = this.state;
        return (
          <div>
            <h2>App Counter: {counter}</h2>
    
            <div className="pages">
              <Home />
              <Profile />
            </div>
          </div>
        );
      }
    }
    
    export default App;
  1. 运行结果

至此,代码仍较为复杂,代码将在React 基础巩固(三十三)中得到优化

相关推荐
777VG1 分钟前
PostgreSQL +martin将多张表输出成一个 MVT
前端·数据库·postgresql
mayaairi32 分钟前
JS循环语句深度解析:嵌套for、while与do...while
开发语言·前端·javascript
To_OC42 分钟前
啃完流式输出:从一个卡顿的 LLM 接口开始,我搞懂了数据流到底怎么 “流”
前端·javascript·llm
阳光是sunny1 小时前
LangGraph实战教程:defer延迟节点——让收尾工作自动排到最后
前端·人工智能·后端
kyriewen1 小时前
我用了三周Claude Code Skills——总结出5条铁律,第3条最反直觉
前端·ai编程·claude
阳光是sunny1 小时前
LangGraph实战教程:控制流详解
前端·人工智能·后端
格尔曼Noah2 小时前
Safari浏览器中如何只允许指定网站下载
前端·safari
用户059540174463 小时前
用了3年Redis,才发现我一直没搞懂缓存一致性测试
前端·css
swipe3 小时前
07|(前端转后全栈)为什么后端也要缓存?从前端缓存思维理解 Redis
前端·后端·全栈
IT小盘3 小时前
05-企业项目统一接入多个大模型-适配器模式实战
前端·人工智能·适配器模式