React 全栈体系(十四)

第七章 redux

六、react-redux

7. 代码 - react-redux 数据共享版

7.1 效果

请添加图片描述

7.2 App
/* src/App.jsx */
import React, { Component } from "react";
import Count from "./containers/Count";
import Person from "./containers/Person";export default class App extends Component {render() {return (<div><Count /><hr /><Person /></div>);}
}
7.3 Count
/* src/containers/Count/index.jsx */
import React, { Component } from "react";
import {createIncrementAction,createDecrementAction,createIncrementAsyncAction,
} from "../../redux/actions/count";//引入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><h2>我是Count组件,下方组件总人数为:{this.props.renshu}</h2><h4>当前求和为:{this.props.count}</h4><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.he, renshu: state.rens.length }),{jia: createIncrementAction,jian: createDecrementAction,jiaAsync: createIncrementAsyncAction,}
)(Count);
7.4 Person
/* src/containers/Person/index.jsx */
import React, { Component } from "react";
import { nanoid } from "nanoid";
import { connect } from "react-redux";
import { createAddPersonAction } from "../../redux/actions/person";class Person extends Component {addPerson = () => {const name = this.nameNode.value;const age = this.ageNode.value;const personObj = { id: nanoid(), name, age };this.props.jiaYiRen(personObj);this.nameNode.value = "";this.ageNode.value = "";};render() {return (<div><h2>我是Person组件,上方组件求和为{this.props.he}</h2><inputref={(c) => (this.nameNode = c)}type="text"placeholder="输入名字"/><inputref={(c) => (this.ageNode = c)}type="text"placeholder="输入年龄"/><button onClick={this.addPerson}>添加</button><ul>{this.props.yiduiren.map((p) => {return (<li key={p.id}>{p.name}--{p.age}</li>);})}</ul></div>);}
}export default connect((state) => ({ yiduiren: state.rens, he: state.he }), //映射状态{ jiaYiRen: createAddPersonAction } //映射操作状态的方法
)(Person);
7.5 store
/* src/redux/store.js */
/*** 该文件专门用于暴露一个store对象,整个应用只有一个store对象*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware, combineReducers } from "redux";
//引入为Count组件服务的reducer
import countReducer from "./reducers/count";
//引入为Person组件服务的reducer
import personReducer from "./reducers/person";
//引入redux-thunk,用于支持异步action
import thunk from "redux-thunk";//汇总所有的reducer变为一个总的reducer
const allReducer = combineReducers({he: countReducer,rens: personReducer,
});
//暴露store
export default createStore(allReducer, applyMiddleware(thunk));
7.6 constant
/* src/redux/constant.js */
/*** 该模块是用于定义action对象中type类型的常量值,目的只有一个:便于管理的同时防止程序员单词写错*/
export const INCREMENT = "increment";
export const DECREMENT = "decrement";
export const ADD_PERSON = "add_person";
7.7 actions
7.5.1 count
/* src/redux/actions/count.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);};
};
7.5.2 person
/* src/redux/actions/person.js */
import { ADD_PERSON } from "../constant";//创建增加一个人的action动作对象
export const createAddPersonAction = (personObj) => ({type: ADD_PERSON,data: personObj,
});
7.8 reducers
7.8.1 count
/* src/redux/reducers/count.js */
/*** 1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数* 2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)*/
import { INCREMENT, DECREMENT } from "../constant";const initState = 0;
export default function countReducer(preState = initState, action) {//从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case INCREMENT: //如果是加return preState + data;case DECREMENT: //如果是减return preState - data;default:return preState;}
}
7.8.2 person
/* src/redux/reducers/person.js */
import { ADD_PERSON } from "../constant";//初始化人的列表
const initState = [{ id: "001", name: "tom", age: 18 }];export default function personReducer(preState = initState, action) {const { type, data } = action;switch (type) {case ADD_PERSON:return [data, ...preState];default:return preState;}
}
7.9 总结
(1).定义一个Person组件,和Count组件通过redux共享数据。
(2).为Person组件编写:reducer、action,配置constant常量。
(3).重点:Person的reducer和Count的Reducer要使用combineReducers进行合并,合并后的总状态是一个对象!!!
(4).交给store的是总reducer,最后注意在组件中取出状态的时候,记得“取到位”。

七、纯函数和高阶函数

1. 纯函数

  • 一类特别的函数: 只要是同样的输入(实参),必定得到同样的输出(返回)
  • 必须遵守以下一些约束
    • 不得改写参数数据
    • 不会产生任何副作用,例如网络请求,输入和输出设备
    • 不能调用 Date.now()或者 Math.random()等不纯的方法
  • redux 的 reducer 函数必须是一个纯函数

2. 高阶函数

  • 理解: 一类特别的函数
    • 情况 1: 参数是函数
    • 情况 2: 返回是函数
  • 常见的高阶函数:
    • 定时器设置函数
    • 数组的 forEach()/map()/filter()/reduce()/find()/bind()
    • promise
    • react-redux 中的 connect 函数
  • 作用: 能实现更加动态, 更加可扩展的功能

八、使用 redux 调试工具

1. 安装 chrome 浏览器插件

请添加图片描述

2. 下载工具依赖包

  • npm install --save-dev redux-devtools-extension

3. 总结

(1).yarn add redux-devtools-extension
(2).store中进行配置import {composeWithDevTools} from 'redux-devtools-extension'const store = createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))

九、react-redux 最终版

请添加图片描述

1. index.js

/* 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包裹App,目的是让App所有的后代容器组件都能接收到store */<Provider store={store}><App /></Provider>,document.getElementById("root")
);

2. App.jsx

/* src/App.jsx */
import React, { Component } from "react";
import Count from "./containers/Count"; //引入的Count容器组件
import Person from "./containers/Person"; //引入的Person容器组件export default class App extends Component {render() {return (<div><Count /><hr /><Person /></div>);}
}

3. store.js

/* src/redux/store.js */
/*** 该文件专门用于暴露一个store对象,整个应用只有一个store对象*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware } from "redux";
//引入汇总之后的reducer
import reducer from "./reducers";
//引入redux-thunk,用于支持异步action
import thunk from "redux-thunk";//暴露store
export default createStore(reducer, applyMiddleware(thunk));

4. containers

4.1 Count
/* src/containers/Count/index.jsx */
import React, { Component } from "react";
import {increment,decrement,incrementAsync,
} from "../../redux/actions/count";//引入connect用于连接UI组件与redux
import { connect } from "react-redux";// 定义UI组件
class Count extends Component {//加法increment = () => {const { value } = this.selectNumber;this.props.increment(value * 1);};//减法decrement = () => {const { value } = this.selectNumber;this.props.decrement(value * 1);};//奇数加incrementIfOdd = () => {const { value } = this.selectNumber;if (this.props.count % 2 !== 0) {this.props.increment(value * 1);}};//异步加incrementAsync = () => {const { value } = this.selectNumber;this.props.incrementAsync(value * 1, 500);};render() {return (<div><h2>我是Count组件,下方组件总人数为:{this.props.personCount}</h2><h4>当前求和为:{this.props.count}</h4><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.count,personCount: state.persons.length,}),{increment,decrement,incrementAsync,}
)(Count);
4.2 Person
/* src/containers/Person/index.jsx */
import React, { Component } from "react";
import { nanoid } from "nanoid";
import { connect } from "react-redux";
import { addPerson } from "../../redux/actions/person";class Person extends Component {addPerson = () => {const name = this.nameNode.value;const age = this.ageNode.value * 1;const personObj = { id: nanoid(), name, age };this.props.addPerson(personObj);this.nameNode.value = "";this.ageNode.value = "";};render() {return (<div><h2>我是Person组件,上方组件求和为{this.props.count}</h2><inputref={(c) => (this.nameNode = c)}type="text"placeholder="输入名字"/><inputref={(c) => (this.ageNode = c)}type="text"placeholder="输入年龄"/><button onClick={this.addPerson}>添加</button><ul>{this.props.personArr.map((p) => {return (<li key={p.id}>{p.name}--{p.age}</li>);})}</ul></div>);}
}export default connect((state) => ({personArr: state.persons,count: state.count,}), //映射状态{ addPerson } //映射操作状态的方法
)(Person);

5. reducers

5.1 index
/* src/redux/reducers/index.js */
/*** 该文件用于汇总所有的reducer为一个总的reducer*/
//引入combineReducers,用于汇总多个reducer
import { combineReducers } from "redux";//引入为Count组件服务的reducer
import count from "./count";
//引入为Person组件服务的reducer
import persons from "./person";//汇总所有的reducer变为一个总的reducer
export default combineReducers({count,persons
});
5.2 count
/* src/redux/reducers/count.js */
/*** 1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数* 2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)*/
import { INCREMENT, DECREMENT } from "../constant";const initState = 0;
export default function countReducer(preState = initState, action) {//从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case INCREMENT: //如果是加return preState + data;case DECREMENT: //如果是减return preState - data;default:return preState;}
}
5.3 person
/* src/redux/reducers/person.js */
import { ADD_PERSON } from "../constant";//初始化人的列表
const initState = [{ id: "001", name: "tom", age: 18 }];export default function personReducer(preState = initState, action) {const { type, data } = action;switch (type) {case ADD_PERSON:return [data, ...preState];default:return preState;}
}

6. actions

6.1 count
/* src/redux/actions/count.js */
/*** 该文件专门为Count组件生成action对象*/
import { INCREMENT, DECREMENT } from "../constant";//同步action,就是指action的值为Object类型的一般对象
export const increment = (data) => ({ type: INCREMENT, data });
export const decrement = (data) => ({ type: DECREMENT, data });//异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的
export const incrementAsync = (data, time) => {return (dispatch) => {setTimeout(() => {dispatch(increment(data));}, time);};
};
6.2 person
/* src/redux/actions/person.js */
import { ADD_PERSON } from "../constant";//创建增加一个人的action动作对象
export const addPerson = (personObj) => ({type: ADD_PERSON,data: personObj,
});

7. 总结

(1).所有变量名字要规范,尽量触发对象的简写形式。
(2).reducers文件夹中,编写index.js专门用于汇总并暴露所有的reducer

十、项目打包

npm run buildnpm install -g serve
serve -s build

请添加图片描述

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

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

相关文章

26947-2011 手动托盘搬运车 学习记录

声明 本文是学习GB-T 26947-2011 手动托盘搬运车. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了手动托盘搬运车(以下简称托盘车)的结构参数、技术要求、试验方法、检验规则、 标志、包装、运输和贮存。 本标准适用于额定载荷…

【数据结构--八大排序】之冒泡排序+选择排序+插入排序

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

2023彩虹全新SUP模板,知识付费模板,卡卡云模板

源码介绍&#xff1a; 2023彩虹全新SUP模板/知识付费模板/卡卡云模板&#xff0c;首页美化&#xff0c;登陆页美化&#xff0c;修复了pc端购物车页面显示不正常的问题。 请自行查毒。感觉彩虹不少源码可能都有不干净的东西 安装教程&#xff1a; 1.将这俩个数据库文件导入数据…

2023.09.30使用golang1.18编译Hel10-Web/Databasetools的windows版

#Go 1.21新增的 log/slog 完美解决了以上问题&#xff0c;并且带来了很多其他很实用的特性。 本次编译不使用log/slog 包 su - echo $GOPATH ;echo $GOROOT; cd /tmp; busybox wget --no-check-certificate https://go.dev/dl/go1.18.linux-amd64.tar.gz;\ which tar&&am…

Java on Azure Tooling 8月更新|以应用程序为中心的视图支持及 Azure 应用服务部署状态改进

作者&#xff1a;Jialuo Gan - Program Manager, Developer Division at Microsoft 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎阅读 Java on Azure 工具的八月更新。在本次更新中&#xff0c;我们将推出新的以应用程序为中心的视图支持&#xff0c;帮助开发人员在一个项…

Python计算巴氏距离

Python计算巴氏距离 巴氏距离简介 在统计中&#xff0c;巴氏距离&#xff08;Bhattacharyya Distance&#xff09;测量两个离散或连续概率分布的相似性。它与衡量两个统计样品或种群之间的重叠量的巴氏系数密切相关。巴氏距离和巴氏系数以20世纪30年代曾在印度统计研究所工作…

<Xcode> Xcode IOS无开发者账号打包和分发

关于flutter我们前边聊到的初入门、数据解析、适配、安卓打包、ios端的开发和黑苹果环境部署&#xff0c;但是对于苹果的打包和分发&#xff0c;我只是给大家了一个链接&#xff0c;作为一个顶级好男人&#xff0c;我认为这样是对大家的不负责任&#xff0c;那么这篇就主要是针…

解决WIFI网络登录困难的方法

当你遇到手机WIFI网络在连接成功后&#xff0c;总是提示网络受限或者当前网络无法连接互联网&#xff0c;但过一段时间后它又自动恢复正常的的问题&#xff0c;可以尝试用以下方法来解决。 第一步&#xff1a;打开WLAN连接设置界面&#xff0c;选择“更多设置” 第二步&#x…

分类预测 | MATLAB实现NGO-CNN北方苍鹰算法优化卷积神经网络数据分类预测

分类预测 | MATLAB实现NGO-CNN北方苍鹰算法优化卷积神经网络数据分类预测 目录 分类预测 | MATLAB实现NGO-CNN北方苍鹰算法优化卷积神经网络数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现NGO-CNN北方苍鹰算法优化卷积神经网络数据分类预测&…

c语言常用语法,长时间不用容易忘。

关键字 auto 声明自动变量const 定义常量&#xff0c;如果一个变量被 const 修饰&#xff0c;那么它的值就不能再被改变extern 声明变量或函数是在其它文件或本文件的其他位置定义register 声明寄存器变量signed 声明有符号类型变量或函数static 声明静态变量&#xff0c;修饰…

c#中的接口

使用IEnumerable统一迭代变量类型 class Program {static void Main(string[] args){int[] nums1 new int[] { 1, 2, 3, 4, 5 };ArrayList nums2 new ArrayList { 1, 2, 3, 4, 5 };Console.WriteLine(Sum(nums1));Console.WriteLine(Sum(nums2));Console.WriteLine(Avg(nums…

Windows系统利用cpolar内网穿透搭建Zblog博客网站并实现公网访问内网!

文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员&#xff0c;自己搭建网站制作网页是绕…

华为智能高校出口安全解决方案(3)

本文承接&#xff1a; https://qiuhualin.blog.csdn.net/article/details/133267254?spm1001.2014.3001.5502 重点讲解华为智能高校出口安全解决方案的攻击防御&安全运维&日志审计的部署流程。 华为智能高校出口安全解决方案&#xff08;3&#xff09; 课程地址攻击防…

【数据结构】【C++】封装哈希表模拟实现unordered_map和unordered_set容器

【数据结构】&&【C】封装哈希表模拟实现unordered_map和unordered_set容器 一.哈希表的完成二.改造哈希表(泛型适配)三.封装unordered_map和unordered_set的接口四.实现哈希表迭代器(泛型适配)五.封装unordered_map和unordered_set的迭代器六.解决key不能修改问题七.实…

家政服务小程序,家政系统开发

家政服务小程序&#xff0c;家政系统开发&#xff0c;打造一线家政系统&#xff0c;提效增收 家政服务小程序 互联网&#xff0b;家政系统&#xff0c;打造互联网&#xff0b;家政公司app开发&#xff0c;支持个性化定制&#xff0c;直接搭建&#xff0c;上手即用&#xff0e;实…

Windows上安装 Go 环境

一、下载go环境 下载go环境&#xff1a;Go下载官网链接找到自己想下载的版本&#xff0c;点击下载&#xff0c;比如我这是windows64位的&#xff0c;我就直接点击最新的。 二、安装go环境 双击下载的.msi文件 next next 他默认的是c盘&#xff0c;你自己可以改&#xff0c;然…

最新影视视频微信小程序源码-带支付和采集功能/微信小程序影视源码PHP(更新)

源码简介&#xff1a; 这个影视视频微信小程序源码&#xff0c;新更新的&#xff0c;它还带支付和采集功能&#xff0c;作为微信小程序影视源码&#xff0c;它可以为用户 提供丰富的影视资源&#xff0c;包括电影、电视剧、综艺节目等。 这个小程序影视源码&#xff0c;还带有…

C语言之内存函数篇(3)

目录 memcpy memcpy的使用 memcpy的模拟实现 NO1. NO2. memcpy可否实现重叠空间的拷贝 my_memcpy memcpy memmove memmove memmove模拟实现 分析 代码 memset memset的使用 memcmp memcmp的使用 <0 0 >0 今天我们继续介绍几个重要的内存操作函…

Celery结合flask完成异步任务与定时任务

Celery 常用于 web 异步任务、定时任务等。 使用 redis 作为 Celery的「消息代理 / 消息中间件」。 这里通过Flask-Mail使用qq邮箱延时发送邮件作为示例 pip install celery pip install redis pip install Flask-Mail1、使用flask发送邮件 使用 Flask-Mail 发送邮件需要进行…

【无标题】ICCV 2023 | CAPEAM:基于上下文感知规划和环境感知记忆机制构建具身智能体

文章链接&#xff1a; https://arxiv.org/abs/2308.07241 2023年&#xff0c;大型语言模型&#xff08;LLMs&#xff09;以及AI Agents的蓬勃发展为整个机器智能领域带来了全新的发展机遇。一直以来&#xff0c;研究者们对具身智能&#xff08;Embodied Artificial Intelligenc…