React 全栈体系(十四)

news2024/11/24 17:18:06

第七章 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>
        <input
          ref={(c) => (this.nameNode = c)}
          type="text"
          placeholder="输入名字"
        />
        <input
          ref={(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、data
  const { 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>
        <input
          ref={(c) => (this.nameNode = c)}
          type="text"
          placeholder="输入名字"
        />
        <input
          ref={(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、data
  const { 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 build

npm install -g serve
serve -s build

请添加图片描述

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

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

相关文章

opencv dnn模块 示例(17) 目标检测 object_detection 之 yolo v5

在前文【opencv dnn模块 示例(16) 目标检测 object_detection 之 yolov4】介绍的yolo v4后的2个月&#xff0c;Ultralytics发布了YOLOV5 的第一个正式版本&#xff0c;其性能与YOLO V4不相伯仲。 文章目录 1、Yolo v5 和 Yolo v4 的区别说明1.1、Data Augmentation - 数据增强1…

Shader中的渲染路径LightMode

文章目录 前言一、在Shader中如何区分不同的渲染路径1、Pass Tag2、LightMode的不同类型 二、在Frame Debug下查看渲染路径之间的区别1、在摄像机可以切换渲染路径2、前向渲染路径3、延迟渲染路径4、顶点照明渲染路径&#xff08;可以看出效果很差&#xff09; 前言 Shader中的…

网络竞品分析:用爬虫技术洞悉竞争对手

概述 网络竞品分析是指通过互联网收集、分析和比较竞争对手的信息&#xff0c;以了解他们的优势和劣势&#xff0c;找出自己的差距和机会&#xff0c;制定有效的竞争策略。网络竞品分析涉及的信息包括竞争对手的产品、价格、渠道、营销、用户反馈等方面。爬虫技术是一种自动化…

电子商务交易产品质量监测实施指南

声明 本文是学习GB-T 42893-2023 电子商务交易产品质量监测实施指南. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件提供了开展电子商务交易的有形产品质量监测的总则&#xff0c;监测准备、监测实施、监测效果评价 与反馈等过程指导…

git的ssh协议走代理拉取代码

1.首先要自己搭建一个代理 https://blog.csdn.net/Jessica_hhh/article/details/133276101https://blog.csdn.net/Jessica_hhh/article/details/133276101 2. 确认机器装过nc&#xff0c;若没有&#xff0c;用yum install -y nc安装 centos 6使用yum安装软件_duang_huang的博…

Machine Learning(study notes)

There is no studying without going crazy Studying alwats drives us crazy 文章目录 DefineMachine LearningSupervised Learning&#xff08;监督学习&#xff09;Regression problemClassidication Unspervised LearningClustering StudyModel representation&#xff08…

多层感知机——MLP

源代码在此处&#xff1a;https://github.com/wepe/MachineLearning/tree/master/DeepLearning Tutorials/mlp 一、多层感知机&#xff08;MLP&#xff09;原理简介 多层感知机&#xff08;MLP&#xff0c;Multilayer Perceptron&#xff09;也叫人工神经网络&#xff08;ANN&…

2023-9-25 JZ24 反转链表

题目链接&#xff1a;反转链表 import java.util.*;/** public class ListNode {* int val;* ListNode next null;* public ListNode(int val) {* this.val val;* }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&…

顺序读写函数的介绍:fgetc fputc

目录 前提须知&#xff1a; 函数介绍&#xff1a; fputc&#xff1a; fpuct写到文件中&#xff0c;这个可以叫做文件流。 文件效果&#xff1a; 若要将fputc写入屏幕中&#xff0c;可以采取以下代码操作&#xff1a; 屏幕效果&#xff1a; fgetc&#xff1a; 使用f…

基于KubeFATE的FATE-LLM任务实战

随着大型语言模型的不断蓬勃发展&#xff0c;相关新模型&#xff0c;新应用和新范式也在不断涌现&#xff0c;自 4 月发布以来&#xff0c;FATE-LLM 已经迭代发布了多个版本&#xff0c;不断完善大语言模型在联邦学习场景下的支持&#xff0c;以解决构建、使用大模型时的数据隐…

基于图像形态学处理的路面裂缝检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ...................................................... %1&#xff1a;从文件夹中读取多个…

Linux基础知识 总结

Linux基础知识 总结 1、Clion的简单介绍 CLion是以IntelliJ为基础&#xff0c;专为开发C及C所设计的跨平台IDE&#xff0c;可以在Windows、Linux及MacOS使用&#xff0c;这里我是在ubuntu 16.0.4基础上安装。2、下载 Linux版Clion的.tar.gz的压缩包 wget https://download.j…

常用数据库validationQuery语句

常用数据库validationQuery语句 validationQuery是用来验证数据库连接的查询语句&#xff0c;这个查询语句必须是至少返回一条数据的SELECT语句。每种数据库都有各自的验证语句&#xff0c; 下表中收集了几种常见数据库的validationQuery。DataBase validationQueryhsqldb …

【voe】channel receive 和 acm 关联走读

每次看服务端的owt的各种adpater都看得懵懵懂懂翻出三年前的客户端webrtc的代码,才觉得舒坦终于知道为啥owt adapter要这么调用了。ChannelReceiveInterface 是AudioReceiveStream 测试需要的 RtpPacketSinkInterface RtpPacketSinkInterface : This class represents a rece…

系统架构设计(最重要的章节)

系统架构设计 软件架构的概述构件软件架构风格 软件架构的概述 架构设计是在需求分析和软件设计之间的过渡阶段 软件架构设计与生命周期 需求分析&#xff1a;问题空间 架构设计SA&#xff1a;解空间 需求->软件架构设计->系统设计 构件 对象 模块 构件 服务 粒度是越来…

RFID智能档案柜助力各大银行实现RFID智能档案管理

在过去的档案管理过程中&#xff0c;银行常常需要进行繁琐的手工操作&#xff0c;包括分类、排序、装钉、手写档案盒信息等。档案存放无序&#xff0c;查找困难&#xff0c;档案管理效率低下。 问题分析 档案工作流程繁琐低效 银行的档案整理过程繁琐&#xff0c;耗时长&…

flask服务鉴权

基本认证&#xff08;Basic Authentication&#xff09;&#xff1a; 这是一种简单的鉴权方式&#xff0c;需要客户端发送用户名和密码&#xff0c;服务器验证后允许或拒绝访问。可以使用 Flask-BasicAuth 扩展来实现。首先&#xff0c;安装扩展&#xff1a; pip install Fla…

JS 拖拽事件

1.drag等拖拽事件 拖放是由拖动与释放两部分组成&#xff0c;拖放事件也分为被拖动元素的相关事件&#xff0c;和容器的相关事件。 被拖动元素的相关事件如下所示&#xff1a; 被拖动元素相关事件: 事件描述dragstart用户开始拖动元素时触发drag元素正在拖动时触发dragend用户…

高性能系统的性能优化技巧:从专家的经验中学习 | 开源日报 No.40

binhnguyennus/awesome-scalability Stars: 48.3k License: MIT 这个项目是一个阅读列表&#xff0c;用于说明可扩展、可靠和高性能大规模系统的模式。该项目通过知名工程师的文章和可信参考资料来解释概念&#xff0c;并从为数以百万计甚至十亿用户提供服务的经过实战验证的系…

74、SpringBoot 整合 Spring Data JDBC

总结&#xff1a;用起来跟 Spring Data JPA 差不多 什么是 JdbcTemplate&#xff1f;&#xff08;Template译为模板&#xff09; Spring 框架对 JDBC 进行封装&#xff0c;使用 JdbcTemplate 方便实现对数据库操作 ★ Spring Data JDBC 既不需要JPA、Hibernate这种ORM框架&a…