Redux 学习笔记

news2024/11/15 21:33:33

在使用 React Redux 前,我们首先了解一下 Redux 的一些基础知识。

Redux 是 JavaScript 应用程序中用于状态管理的容器。它不依赖于任何框架,可以与任何 UI 库和框架一起使用。在应用程序中使用 Redux 时,Redux 是以可预测的方式管理状态。

Redux 的核心概念

  1. Store

应用系统中需要管理的数据,全部集中在这里

  1. Action

数据的处理都存放在这里,例如数据的添加、删除操作等

  1. Reducer

数据接收和转换存放在这里

Store、Action 和 Reducer 的三者关系

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Redux 的使用原则

  1. 应用程序的状态存储形式是单个对象树

  2. 状态的获取必须通过Action来执行,在Action中我们存放着对应很多动作的key,我们只有执行对应的动作后才能拿到数据

  3. 拿到的数据必须通过Reducer来转换状态树的数据,而Reducer在执行时会拿到Action对应的动作,并接受返回的数据然后进行处理

Actions 说明

Action 的创建如下:

// 定义一个action
function buyCake() {
  return {
    type: BUY_CAKE,
    info: "First redux action",
  };
}

从上述的创建过程来看,action 其实是一个函数并且返回一个对象,其中返回的对象必须带有type属性,这个属性在后续调用的时候会用到。

其次就是除了type属性外,我们还可以根据自己的业务需求来扩展action的属性。

Reducers 说明

Reducers 是专门负责接受状态并且执行对应的action,并把执行完成后跟新对应的状态。

定义一个 Reducer 的过程很简单,具体代码如下:

// 定义一个 state
const initialState = {
  numOfCakes: 20,
};

// 定义一个 reducer
const reducer = (state = initialState, action) => {
  switch (action.type) {
    case BUY_CAKE:
      return {
        numOfCakes: state.numOfCakes - 1,
      };

    default:
      return state;
  }
};

从上述的代码中可以看出Reducer本质也是一个函数,并且接受两个函数。其中第一个参数是Store,而第二个参数是action,并且通过 type 来决定对状态执行什么操作。

Store 说明

Store 的职责主要包括如下几点:

  1. 负责保存应用程序状态
  2. 对外暴露getState的方法,通过此方法可以获取到应用程序中的状态值
  3. 提供了一个dispatch(action)的方法,主要是用于调度对应的action,从而修改状态值
  4. 提供了一个注册监听器的方法subscribe(listener),每当状态发生改变的时候都会触发此函数
  5. 提供了一个取消监听器的方法,用于收回已注册的监听器

实现Store的过程如下:

const redux = require("redux");
const createStoreFn = redux.createStore; // 已经过时,这里只是展示概念性的东西,所以采用了旧方法
const store = createStoreFn(reducer); // 管理对应的状态
console.log(store.getState()); // 使用对外暴露获取状态数据的方法

// 注册监听器
const unsubscribe = store.subscribe(() =>
  console.log("update state", store.getState())
);

// 调用对应的 action 方法
store.dispatch(buyCake());
store.dispatch(buyCake());
store.dispatch(buyCake());

unsubscribe();

如何实现多个 Reducers

只用一个 Reducers 来管理状态

function buyIceCream() {
  return {
    type: BUY_ICECREAM,
  };
}

// 定义一个 State
const initialState = {
  numOfCakes: 20,
  numOfIceCream: 20,
};

// 定义一个 reducer
const reducer = (state = initialState, action) => {
  switch (action.type) {
    case BUY_CAKE:
      return {
        ...state,
        numOfCakes: state.numOfCakes - 1,
      };
    case BUY_ICECREAM:
      return {
        ...state,
        numOfIceCream: state.numOfIceCream - 1,
      };
    default:
      return state;
  }
};

通过上述的实例代码可以看出,我们只是简单的添加了一个actionReducer就需要添加一个对应的状态处理方法,假如我们的业务逻辑比较复杂的话Reducer则会变得非常难以维护,所以我们可以使用多个Reducer来分解对状态处理的方法。

实现多个 Reducers

在实现多个 Reducers 的时候,我们需要用到combineReducers来帮我们注册对应的Rducer。具体的代码实例如下:

const initialCakeState = {
  numOfCakes: 20,
};
const initialIceCreamState = {
  numOfIceCream: 20,
};

const cakeReducer = (state = initialCakeState, action) => {
  switch (action.type) {
    case BUY_CAKE:
      return {
        ...state,
        numOfCakes: state.numOfCakes - 1,
      };
    default:
      return state;
  }
};

const iceCreamReducer = (state = initialIceCreamState, action) => {
  switch (action.type) {
    case BUY_ICECREAM:
      return {
        ...state,
        numOfIceCream: state.numOfIceCream - 1,
      };
    default:
      return state;
  }
};

const rootReducer = combineReducers({
  cake: cakeReducer,
  iceCream: iceCreamReducer,
});
const store = createStoreFn(rootReducer);
const unsubscribe = store.subscribe(() =>
  console.log("update state", store.getState())
);
console.log(store.getState());

// 调用对应的 action 方法
store.dispatch(buyCake());
store.dispatch(buyCake());
store.dispatch(buyCake());

store.dispatch(buyIceCream());
store.dispatch(buyIceCream());

unsubscribe();

如何实现异步 Actions

上述的操作都是同步的,而接下来我们来实现一下异步的Actions

我们以获取用户列表数据为例一步一步实现异步 Actions。

  1. 定义State

因为要实现异步的 Actions,所以我们的数据获取和处理会有一定处理时间,所以对应的State属性应该包括如下几个属性:loadinguserserror。具体代码如下:

const initialState = {
  loading: false, // 判断是否已经获取到数据
  users: [],
  error: "",
};
  1. 实现对应的 Actions

有了对应的状态数据,我们就可以编写一些对应的 Action 功能。具体的实例代码如下:

const FETCH_USERS_REQUEST = "FETCH_USERS_REQUEST";
const FETCH_USERS_SUCCESS = "FETCH_USERS_SUCCESS";
const FETCH_USERS_FAILURE = "FETCH_USERS_FAILURE";

const fetchUsersRequest = () => {
  return {
    type: FETCH_USERS_REQUEST,
  };
};

const fetchUserSuccess = (users) => {
  return {
    type: FETCH_USERS_SUCCESS,
    payload: users,
  };
};

const fetchUserFaikuer = (error) => {
  return {
    type: FETCH_USERS_FAILURE,
    payload: error,
  };
};
  1. 实现对应的 Reducer

有了状态和执行动作,我们就可以实现对应的 Reducer。具体的代码如下:

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_USERS_REQUEST:
      return {
        ...state,
        lading: true,
      };
    case FETCH_USERS_SUCCESS:
      return {
        loading: false,
        users: action.payload,
        error: "",
      };
    case FETCH_USERS_FAILURE:
      return {
        loading: false,
        users: [],
        error: action.payload,
      };
  }
};
  1. StateActionsReducer建立关系

有了上述的准备,现在我们就可以把这三个元素建立关系。

在建立关系之前我们需要安装两个工具:

npm install axios redux-thunk

我们使用 redux 的中间件来实现异步的数据获取。具体代码如下:

const appluMiddleware = redux.applyMiddleware;
const thunkMiddleware = require("redux-thunk").default;
const axios = require("axios");

const store = createStoreFn(reducer, appluMiddleware(thunkMiddleware));

const fetchUsers = () => {
  return function (dispatch) {
    dispatch(fetchUsersRequest());
    axios
      .get("https://jsonplaceholder.typicode.com/users")
      .then((response) => {
        console.log(response);
        const users = response.data.map((user) => user.id);
        dispatch(fetchUserSuccess(users));
      })
      .catch((error) => {
        dispatch(fetchUserFaikuer(error.message));
      });
  };
};

store.subscribe(() => {
  console.log(store.getState());
});
store.dispatch(fetchUsers());

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1113921.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙HarmonyOS应用开发:扫描仪文件扫描

华为鸿蒙HarmonyOS已经发展到4.0,使用ArkTS作为开发语言。这篇文章结合Dynamsoft Service开发一个简单的鸿蒙应用,用来获取办公室里连接PC的扫描仪(惠普,富士通,爱普生,等),把文档扫描到手机里。 准备工作…

Python 3.12.0 Release 版本

本心、输入输出、结果 文章目录 Python 3.12.0 Release 版本前言与 Python 3.11 相比,Python 3.12 系列主要更新了哪些新的功能更灵活的 f 字符串解析,允许许多以前不允许的事情 (PEP 701)。支持 Python 代码中的缓冲区协议 &…

Unity实现方圆X范围随机生成怪物

using System.Collections; using System.Collections.Generic; using UnityEngine;public class CreatMonster : MonoBehaviour {// S这个脚本间隔一点时间生成怪物/*1.程序逻辑* 1. 设计一个计时器* 2.间隔一段时间3s执行一下 * */float SaveTime 0f;public GameObject …

【215. 数组中的第K个最大元素】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 class Solution { public:int getRandom(int left,int right,vector<int>& nums){return nums[rand()%(right-left1)left];}int qsort(int l,int r,vector<int>& nums…

已经有多人中招,不要被AI换脸技术骗了!

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

LinkedList 源码解析(JDK1.8)

目录 一. 前言 二. 常用方法 三. 源码解析 3.1. 属性和内部类 3.2. 构造函数 3.3. 添加元素 3.4. 获取元素 3.5. 删除元素 3.6. 迭代器 3.6.1. 头到尾方向的迭代 3.6.2. 尾到头方向的迭代 3.6.3. add() 插入元素 3.6.4. remove() 移除元素 一. 前言 LinkedList同时…

ATA-8202射频功率放大器参数指标及应用介绍

ATA-8202射频功率放大器简介 ATA-8202是一款射频功率放大器。其P1dB输出功率100W&#xff0c;饱和输出功率200W。增益数控可调&#xff0c;一键保存设置&#xff0c;提供了方便简洁的操作选择&#xff0c;可与主流的信号发生器配套使用&#xff0c;实现射频信号的完美放大。宽…

JavaScript 中的Hoisting是什么?

在JavaScript中,Hoisting(变量提升)是指在代码执行之前,JavaScript引擎将变量和函数的声明提升到当前作用域的顶部的行为。 具体来说,JavaScript引擎在执行代码之前会进行两个步骤:编译阶段和执行阶段。在编译阶段,JavaScript引擎会将变量声明和函数声明提升到当前作用…

智能井盖监测系统,增加城市管理便捷性

看起来小小的井盖&#xff0c;实际上折射的是一个城市&#xff0c;一个地区的发展状况。每一个城市的道路网络&#xff0c;决定了一个城市发展的缓慢程度&#xff0c;哪怕是其中的井盖&#xff0c;有着自己的职责&#xff0c;是城市生命线的不可缺少的组成部分。但是现如今传统…

Qt10-19

第一个界面的头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QMovie>//动态图片所用的类 #include<QMessageBox>//消息对话框类QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget …

国产主控应用案例:汉王电子血压计-君正开发板

2023春季新品发布会上汉王科技发布柯氏音法电子血压计产品—汉王电子血压计&#xff0c;继嗅觉检测盒之后再次深度布局大健康领域。 不同于当前市面上使用示波法原理的电子血压计&#xff0c;汉王电子血压计采用血压测量金标准中的柯氏音法&#xff0c;由此引领一场电子血压计领…

出东方利中国!长城五星牵手国家宝藏,共谱丝路艺术华章

执笔 | 尼 奥 编辑 | 古利特 当中国葡萄酒与国家宝藏、非遗工艺灵魂碰撞&#xff0c;又将产生怎样的大国之美&#xff1f;长城五星艺术干红给出答案。 10月19日&#xff0c;长城五星艺术干红上市发布会在成都召开。会上&#xff0c;长城葡萄酒正式发布文化战略新品——“五…

“达观杯”智能文档版面分析赛题baseline已上线,欢迎下载报名!

由国内领先智能文本处理企业达观数据与上海市计算机学会联合举办的智能文档版面分析多模态数据处理算法竞赛正在火热报名阶段。开赛一周内&#xff0c;第七届“达观杯”已有来自国内外的近200名企业和高校算法精英参与到比赛中。作为本次赛题的出题方&#xff0c;为助力各位打榜…

taro使用defineConstants定义全局变量eslint报错该变量不存在

问题描述 在taro项目中使用defineConstants定义一些全局变量供业务代码中进行使用&#xff0c;全局变量声明config/index.js代码如下&#xff1a; module.exports {defineConstants: {LOGIN_URL: JSON.stringify(/baidu/login), },全局变量使用代码如下&#xff1a; /*** 跳…

高速DSP系统设计参考指南(四)DSP电源设计

&#xff08;四&#xff09;DSP电源设计 1.电源设计的重要性2.DSP电源架构考虑3.电源去耦技术3.1 一般经验法则解耦法3.2 解耦分析方法3.3 分析案例3.4 计算去耦电容值3.5 高频噪声隔离 1.电源设计的重要性 电源设计可能是高速 DSP 设计中控制噪声和辐射的整个过程中最具挑战性…

Affinity Photofor Mac/Windows:专业级图片编辑的终极选择

在今天的内容中&#xff0c;我们将要介绍一款备受赞誉的图片编辑软件——Affinity Photo。无论你是业余的摄影爱好者&#xff0c;还是专业的设计师&#xff0c;Affinity Photo都能为你提供丰富的编辑功能和出色的使用体验。 首先&#xff0c;让我们来简单了解一下Affinity Pho…

哪些重生奇迹mu地图适合刷玛雅宝石?

作为一款非常经典的打斗游戏&#xff0c;重生奇迹mu设计非常复杂&#xff0c;游戏玩法以及地图设计非常完善&#xff0c;而且游戏推出了最新版本&#xff0c;各方面表现更加的优秀&#xff0c;值得游戏玩家去尝试。 重生奇迹mu游戏拥有非常完善的商城系统&#xff0c;其中最重…

金融机器学习方法:决策树与随机森林

目录 1.决策树 1.1 什么是决策树&#xff1f; 1.2 决策树的优点与缺点 2.随机森林 2.1 什么是随机森林&#xff1f; 2.2 随机森林的优点与缺点 3.决策树与随机森林的联系与区别 4.案例分析 4.1 使用决策树和随机森林预测 4.2绘制ROC曲线 决策树和随机森林都是监督学…

聊聊Android线程优化这件事

一、背景 在日常开发APP的过程中&#xff0c;难免需要使用第二方库和第三方库来帮助开发者快速实现一些功能&#xff0c;提高开发效率。但是&#xff0c;这些库也可能会给线程带来一定的压力&#xff0c;主要表现在以下几个方面&#xff1a; 线程数量增多&#xff1a;一些库可…

uniapp——自定义组件插槽及使用

案例样式 自定义组件pageBox.vue <template><view><view class"bgColor" :style"{ height: bgHeight rpx }"></view><view class"main"><!-- 主要内容放这里 --><slot></slot></view>&…