React 全栈体系(十三)

news2024/11/18 5:30:28

第七章 redux

五、redux 异步编程

1. 理解

  • redux 默认是不能进行异步处理的,
  • 某些时候应用中需要在 redux 中执行异步任务(ajax, 定时器)

2. 使用异步中间件

  • npm install --save redux-thunk

3. 代码 - 异步 action 版

3.1 store
/* src/redux/store.js */
/**
 * 该文件专门用于暴露一个store对象,整个应用只有一个store对象
 */
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware } from "redux";
//引入为Count组件服务的reducer
import countReducer from "./count_reducer";
//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
//暴露store
export default createStore(countReducer, applyMiddleware(thunk));
3.2 count_action
/* src/redux/count_action.js */
/**
 * 该文件专门为Count组件生成action对象
 */
import { INCREMENT, DECREMENT } from "./constant";

//同步action,就是指action的值为Object类型的一般对象
export const createIncrementAction = (data) => ({ type: INCREMENT, data });
export const createDecrementAction = (data) => ({ type: DECREMENT, data });

//异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的
export const createIncrementAsyncAction = (data, time) => {
  return (dispatch) => {
    setTimeout(() => {
      dispatch(createIncrementAction(data));
    }, time);
  };
};
3.3 Count
/* src/components/Count/index.jsx */
import React, { Component } from "react";
//引入store,用于获取redux中保存状态
import store from "../../redux/store";
//引入actionCreator,专门用于创建action对象
import {
  createDecrementAction,
  createIncrementAction,
  createIncrementAsyncAction,
} from "../../redux/count_action";

export default class Count extends Component {
  //加法
  increment = () => {
    const { value } = this.selectNumber;
    store.dispatch(createIncrementAction(value * 1));
  };
  //减法
  decrement = () => {
    const { value } = this.selectNumber;
    store.dispatch(createDecrementAction(value * 1));
  };
  //奇数加
  incrementIfOdd = () => {
    const { value } = this.selectNumber;
    const count = store.getState();
    if (count % 2 !== 0) {
      store.dispatch(createIncrementAction(value * 1));
    }
  };
  //异步加
  incrementAsync = () => {
    const { value } = this.selectNumber;
    store.dispatch(createIncrementAsyncAction(value * 1, 500));
  };
  render() {
    return (
      <div>
        <h1>当前求和为:{store.getState()}</h1>
        <select ref={(c) => (this.selectNumber = c)}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        &nbsp;
        <button onClick={this.increment}>+</button>&nbsp;
        <button onClick={this.decrement}>-</button>&nbsp;
        <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
        <button onClick={this.incrementAsync}>异步加</button>
      </div>
    );
  }
}
3.4 总结
(1).明确:延迟的动作不想交给组件自身,想交给action
(2).何时需要异步action:想要对状态进行操作,但是具体的数据靠异步任务返回。
(3).具体编码:
	1).yarn add redux-thunk,并配置在store中
	2).创建action的函数不再返回一般对象,而是一个函数,该函数中写异步任务。
	3).异步任务有结果后,分发一个同步的action去真正操作数据。
(4).备注:异步action不是必须要写的,完全可以自己等待异步任务的结果了再去分发同步action。

六、react-redux

在这里插入图片描述

1. 理解

  • 一个 react 插件库
  • 专门用来简化 react 应用中使用 redux

2. react-Redux 将所有组件分成两大类

2.1 UI 组件
  • 只负责 UI 的呈现,不带有任何业务逻辑
  • 通过 props 接收数据(一般数据和函数)
  • 不使用任何 Redux 的 API
  • 一般保存在 components 文件夹下
2.2 容器组件
  • 负责管理数据和业务逻辑,不负责 UI 的呈现
  • 使用 Redux 的 API
  • 一般保存在 containers 文件夹下
2.3 相关 API
2.3.1 Provider:让所有组件都可以得到 state 数据
<Provider store={store}>
  <App />
</Provider>
2.3.2 connect:用于包装 UI 组件生成容器组件
import { connect } from 'react-redux'
  connect(
    mapStateToprops,
    mapDispatchToProps
  )(Counter)
2.3.3 mapStateToprops:将外部的数据(即 state 对象)转换为 UI 组件的标签属性
const mapStateToprops = function (state) {
  return {
    value: state
  }
}
2.3.4 mapDispatchToProps:将分发 action 的函数转换为 UI 组件的标签属性

3. 代码 - react-redux 的基本使用

  • 安装:npm install react-redux
3.1 index
/* src/index.js */
//引入react核心库
import React from "react";
//引入ReactDOM
import ReactDOM from "react-dom";
//引入App组件
import App from "./App";
import store from "./redux/store";

ReactDOM.render(<App />, document.getElementById("root"));
//监测redux中状态的改变,如redux的状态发生了改变,那么重新渲染App组件
store.subscribe(() => {
  ReactDOM.render(<App />, document.getElementById("root"));
});
3.2 App
/* src/App.jsx */
import React, { Component } from "react";
import Count from "./containers/Count";
import store from "./redux/store";

export default class App extends Component {
  render() {
    return (
      <div>
        {/* 给容器组件传递store */}
        <Count store={store} />
      </div>
    );
  }
}
3.3 Count(Component)
/* src/components/Count/index.jsx */
import React, { Component } from "react";

export default class Count extends Component {
  //加法
  increment = () => {
    const { value } = this.selectNumber;
    this.props.jia(value * 1);
  };
  //减法
  decrement = () => {
    const { value } = this.selectNumber;
    this.props.jian(value * 1);
  };
  //奇数加
  incrementIfOdd = () => {
    const { value } = this.selectNumber;
    if (this.props.count % 2 !== 0) {
      this.props.jia(value * 1);
    }
  };
  //异步加
  incrementAsync = () => {
    const { value } = this.selectNumber;
    this.props.jiaAsync(value * 1, 500);
  };
  render() {
    return (
      <div>
        <h1>当前求和为:{this.props.count}</h1>
        <select ref={(c) => (this.selectNumber = c)}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        &nbsp;
        <button onClick={this.increment}>+</button>&nbsp;
        <button onClick={this.decrement}>-</button>&nbsp;
        <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
        <button onClick={this.incrementAsync}>异步加</button>
      </div>
    );
  }
}
3.4 Count(Container)
/* src/containers/Count/index.jsx */
//引入Count的UI组件
import CountUI from "../../components/Count";
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction,
} from "../../redux/count_action";

//引入connect用于连接UI组件与redux
import { connect } from "react-redux";

/*
	1.mapStateToProps函数返回的是一个对象;
	2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
	3.mapStateToProps用于传递状态
*/
function mapStateToProps(state) {
  return { count: state };
}

/*
	1.mapDispatchToProps函数返回的是一个对象;
	2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
	3.mapDispatchToProps用于传递操作状态的方法
*/
function mapDispatchToProps(dispatch) {
  return {
    jia: (number) => dispatch(createIncrementAction(number)),
    jian: (number) => dispatch(createDecrementAction(number)),
    jiaAsync: (number, time) =>
      dispatch(createIncrementAsyncAction(number, time)),
  };
}
//使用connect()()创建并暴露一个Count的容器组件
export default connect(mapStateToProps, mapDispatchToProps)(CountUI);
3.5 总结
(1).明确两个概念:
	1).UI组件:不能使用任何redux的api,只负责页面的呈现、交互等。
	2).容器组件:负责和redux通信,将结果交给UI组件。
(2).如何创建一个容器组件————靠 react-redux 的 connect函数
	connect(mapStateToProps,mapDispatchToProps)(UI组件)
		-mapStateToProps:映射状态,返回值是一个对象
		-mapDispatchToProps:映射操作状态的方法,返回值是一个对象
(3).备注1:容器组件中的store是靠props传进去的,而不是在容器组件中直接引入
(4).备注2:mapDispatchToProps,也可以是一个对象

4. 代码 - 优化 1:简写 mapDispatch

Count(Container)
/* src/containers/Count/index.jsx */
//引入Count的UI组件
import CountUI from "../../components/Count";
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction,
} from "../../redux/count_action";

//引入connect用于连接UI组件与redux
import { connect } from "react-redux";

//使用connect()()创建并暴露一个Count的容器组件
export default connect((state) => ({ count: state }), {
  jia: createIncrementAction,
  jian: createDecrementAction,
  jiaAsync: createIncrementAsyncAction,
})(CountUI);

5. 代码 - 优化 2:Provider 组件的使用

5.1 index
/* src/index.js */
//引入react核心库
import React from "react";
//引入ReactDOM
import ReactDOM from "react-dom";
//引入App组件
import App from "./App";
import store from "./redux/store";
import { Provider } from "react-redux";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);
5.2 App
/* src/App.jsx */
import React, { Component } from "react";
import Count from "./containers/Count";

export default class App extends Component {
  render() {
    return (
      <div>
        <Count />
      </div>
    );
  }
}

6. 代码 - 优化 3:整合 UI 组件和容器组件

6.1 Count(Container)
/* src/containers/Count/index.jsx */
import React, { Component } from "react";
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction,
} from "../../redux/count_action";

//引入connect用于连接UI组件与redux
import { connect } from "react-redux";

// 定义UI组件
class Count extends Component {
  //加法
  increment = () => {
    const { value } = this.selectNumber;
    this.props.jia(value * 1);
  };
  //减法
  decrement = () => {
    const { value } = this.selectNumber;
    this.props.jian(value * 1);
  };
  //奇数加
  incrementIfOdd = () => {
    const { value } = this.selectNumber;
    if (this.props.count % 2 !== 0) {
      this.props.jia(value * 1);
    }
  };
  //异步加
  incrementAsync = () => {
    const { value } = this.selectNumber;
    this.props.jiaAsync(value * 1, 500);
  };
  render() {
    return (
      <div>
        <h1>当前求和为:{this.props.count}</h1>
        <select ref={(c) => (this.selectNumber = c)}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        &nbsp;
        <button onClick={this.increment}>+</button>&nbsp;
        <button onClick={this.decrement}>-</button>&nbsp;
        <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
        <button onClick={this.incrementAsync}>异步加</button>
      </div>
    );
  }
}


//使用connect()()创建并暴露一个Count的容器组件
export default connect((state) => ({ count: state }), {
  jia: createIncrementAction,
  jian: createDecrementAction,
  jiaAsync: createIncrementAsyncAction,
})(Count);
6.2 总结
(1).容器组件和UI组件整合一个文件
(2).无需自己给容器组件传递store,给<App/>包裹一个<Provider store={store}>即可。
(3).使用了react-redux后也不用再自己检测redux中状态的改变了,容器组件可以自动完成这个工作。
(4).mapDispatchToProps也可以简单的写成一个对象
(5).一个组件要和redux“打交道”要经过哪几步?
	(1).定义好UI组件---不暴露
	(2).引入connect生成一个容器组件,并暴露,写法如下:
			connect(
				state => ({key:value}), //映射状态
				{key:xxxxxAction} //映射操作状态的方法
			)(UI组件)
	(3).在UI组件中通过this.props.xxxxxxx读取和操作状态

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

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

相关文章

全景剖析|国产芯(CPU、GPU、SSD、NAND、DRAM)虽有突破,但路还很长

这两天小编看到两个有关国产芯的消息,很有感触,本文小编分享下所思所想,如有不当之处,还望包涵,可以留言指正! 第一个消息是:近日,华为轮值主席 徐直军在2023世界计算大会上,有个国产芯的呼吁,“我们不要抱有幻想,应该坚定不移的打造可持续发展的计算产业生态。从计…

Webpack打包时Bable解决浏览器兼容问题

当我们使用js新特性语法编写代码时&#xff0c;在旧的浏览器中兼容性并不好。但是我们希望能够在旧浏览器中使用这些新特性。 使用babel可以使js新代码转换为js旧代码&#xff0c;增加浏览器的兼容性。 如果我们希望在Webpack中支持babel&#xff0c;则需要在Webpack中引入bab…

【C++】静态成员函数 ( 静态成员函数概念 | 静态成员函数声明 | 静态成员函数访问 | 静态成员函数只能访问静态成员 )

文章目录 一、静态成员函数简介1、静态成员函数概念2、静态成员函数声明3、静态成员函数访问4、静态成员函数只能访问静态成员 二、代码示例 - 静态成员函数 一、静态成员函数简介 1、静态成员函数概念 静态成员函数归属 : 在 C 类中 , 静态成员函数 是一种 特殊的函数 , 该函数…

记一次manjaro-i3系统sogoupinying候选词无法正常显示中文(变方框了)问题解决方案

记一次manjaro-i3系统sogoupinying候选词无法正常显示中文&#xff08;变方框了&#xff09;问题解决方案 前言解决方案 前言 今天早上发现公司电脑显卡驱动好像坏了&#xff0c;各种折腾完了干脆把系统搞黑屏无法开机了&#xff0c;时间有限懒再修了&#xff0c;于是重装了系…

【C++面向对象侯捷下】1.导读

文章目录 来源&#xff1a;我的百度网盘 百科全书 专家书籍 C标准库 C编译器

解锁学习新方式——助您迈向成功之路

近年来&#xff0c;随着吉林开放大学广播电视大学的崛起&#xff0c;越来越多的学子选择这所优秀的学府来实现自己的梦想。而作为一名学者&#xff0c;我有幸见证了电大搜题微信公众号的诞生&#xff0c;为广大学子提供了一个全新的学习支持平台。 电大搜题微信公众号&#xff…

解决老版本Oracle VirtualBox 此应用无法在此设备上运行问题

问题现象 安装华为eNSP模拟器的时候&#xff0c;对应的Oracle VirtualBox-5.2.26安装的时候提示兼容性问题&#xff0c;无法进行安装&#xff0c;具体版本信息如下&#xff1a; 软件对应版本备注Windows 11专业工作站版22H222621eNSP1.3.00.100 V100R003C00 SPC100终结正式版…

Android studio安卓生成APK文件安装包方法

1.点击Build->Generate Signed Bundle/APK 2.选择APK 3.首次生成&#xff0c;没有jks文件&#xff0c;就点击Create new。再次生成&#xff0c;直接点Next 4.选择创建jks文件路径 5.点击Next 6.选择release 7.生成完成的apk安装包路径

PostgreSql 统一修改date字段为timestamp

在《Powdersigner PostgreSql 同步表结构到pg数据库》中&#xff0c;导入表结构到pg数据后&#xff0c;发下时间对不上了。mysql的datetime转换后pg的变成了date了。 再同步到数据后&#xff0c;就变成日期类型了。 因为表中基本都有创建时间和修改时间&#xff0c;两个相对固…

电脑桌面透明便签软件是哪个?

在现代快节奏的工作环境中&#xff0c;许多上班族都希望能够在电脑桌面上方便地记录工作资料、重要事项、工作流程等内容。为了解决这个问题&#xff0c;一款优秀的电脑桌面便签软件是必不可少的。在选择桌面便签软件时&#xff0c;许多用户也希望便签软件能够与电脑桌面壁纸相…

文件操作(1)

1. 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失 了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久…

CBOW (以txt文本小说为例) pytorch实战

CBOW &#xff08;以txt文本小说为例 pytorch实战 今天博主做了一个不错的实验&#xff0c;我认为&#xff0c;很多小伙伴可能都可以从中学到东西。 我先说一下这个实验&#xff0c;我做了什么&#xff0c;在这个实验中&#xff0c;博主会从零&#xff0c;开始从一个txt文件开…

从零开始的 MyBatis 拦截器之旅:实战经验分享

文章目录 MyBatis拦截器可以做什么&#xff1f;Mybatis核心对象介绍四大核心对象如何实现&#xff1f;接口讲解Interceptor接口intercept方法plugin方法setProperties 完整SQL打印拦截器实战拦截器实现拦截器注册 MyBatis拦截器可以做什么&#xff1f; MyBatis拦截器是MyBatis…

某手新版本sig3参数算法还原

Frida Native层主动调用 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 75 76 77 78 79 80 81…

#循循渐进学51单片机#指针基础与1602液晶的初步认识#not.11

1、把本节课的指针相关内容&#xff0c;反复学习3到5遍&#xff0c;彻底弄懂指针是怎么回事&#xff0c;即使是死记硬背也要记住&#xff0c;等到后边用的时候可以实现顿悟。学会指针&#xff0c;就是突破了C语言的一道壁垒。 2&#xff0c;1602所有的指令功能都应用一遍&#…

内网穿透,轻松实现PostgreSQL数据库公网远程连接!

文章目录 前言1. 安装postgreSQL2. 本地连接postgreSQL3. Windows 安装 cpolar4. 配置postgreSQL公网地址5. 公网postgreSQL访问6. 固定连接公网地址7. postgreSQL固定地址连接测试 前言 PostgreSQL是一个功能非常强大的关系型数据库管理系统&#xff08;RDBMS&#xff09;,下…

外汇天眼:CFTC处罚Advantage Futures 39.5万美元

美国商品期货交易委员会&#xff08;CFTC&#xff09;对Advantage Futures处以39.5万美元罚款&#xff0c;原因是其监管不力。 CFTC今天发布了一项命令&#xff0c;同时提起并解决了对Advantage Futures LLC的指控&#xff0c;这是一家注册的期货佣金经纪商&#xff0c;因未能…

Linux命令基础

一、linux目录结构。 Linux没有windows的盘的概念&#xff0c;是一个树形的结构。唯一的根目录为/&#xff0c;所有的文件都在他下面。 描述方式也与windows有所不同 二、命令基础格式。 command [-options] [parameter]&#xff08;[ ]表示可选的&#xff09; command:必…

智思Ai企联系统去授权版本+uniapp前后端(内含教程)

智思AI企联系统是一款企业级AI系统&#xff0c;与普通版AI产品相比具备显著差异。该系统允许企业按需选择和定制二开任意功能&#xff0c;以满足不同企业的个性化需求和场景要求。企业可以根据实际业务需求扩展和改进系统功能模块&#xff0c;使之更好地适应企业独特需求。

ESP8266 WiFi物联网智能插座—电能计量

目录 1、芯片功能 2、性能指标 3、寄存器说明 4、UART通信协议 4.1、写操作帧格式和时序 4.2、读操作帧格式和时序 4.3、读取全电参数数据包 4.4、配置波特率 4.5、UART保护机制 5、功能说明 5.1、电流电压瞬态波形计量 5.2、有功功率 5.3、有功功率防潜动 5.4、电能计量 5.5、…