【前端知识】React 基础巩固(三十七)——自定义connect高阶组件

React 基础巩固(三十七)——自定义connect高阶组件

一、手撸一个自定义connect高阶组件

import { PureComponent } from "react";
import store from "../store";/*** connect的参数:* 参数一: 函数* 参数二: 函数* 返回值: 函数*/
export default function connect(mapStateToProps, mapDispatchToProps) {// 返回一个高阶组件,本质也是函数return function (WrapperComponent) {class NewComponent extends PureComponent {constructor(props) {super(props);// 将接收到的mapStateToProps赋给state,用于部分值修改时的浅层比较、更新statethis.state = mapStateToProps(store.getState());}componentDidMount() {this.unsubscribe = store.subscribe(() => {this.setState(mapStateToProps(store.getState()));});}componentWillUnmount() {this.unsubscribe();}render() {// 将接收到的mapStateToProps、mapDispatchToProps传入要返回的新组件中const stateObj = mapStateToProps(store.getState());const dispatchObj = mapDispatchToProps(store.dispatch);return (<WrapperComponent {...this.props} {...stateObj} {...dispatchObj} />);}}return NewComponent;};
}

二、目前的问题

import store from "../store";

从这行代码可以看到,目前的connect直接引用了上级目录的store,过于依赖目前既定的store,这样不利于复用。假设另一个项目的store所在位置不在上级目录中,则会出现问题。

三、优化上面的丐版connect

为了让所有人都能使用,我们应该把这种“写死”的做法换成让开发者自己传入一个store:

  1. 构建一个StoreContext,用于创建Store的上下文(src/hoc/StoreContext.js):

    import { createContext } from "react";export const StoreContext = createContext()
    
  2. 当我们在项目的index.js中引入connect时,引入并使用该上下文,让开发者手动传入当前的store(src/index.js):

    import React from "react";
    import ReactDOM from "react-dom/client";
    import { Provider } from "react-redux";
    import { StoreContext } from "./hoc";
    import App from "./App";
    import store from "./store";const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(// <React.StrictMode><Provider store={store}><StoreContext.Provider value={store}><App /></StoreContext.Provider></Provider>// </React.StrictMode>
    );
  3. 在connect中,通过 contextType 共享从 Provider 中传入的 store 变量,将原来直接引用的 store 替换成 this.context(hoc/connect.js):

    import { PureComponent } from "react";
    import { StoreContext } from "./StoreContext";/*** connect的参数:* 参数一: 函数* 参数二: 函数* 返回值: 函数*/
    export function connect(mapStateToProps, mapDispatchToProps) {// 返回一个高阶组件,本质也是函数return function (WrapperComponent) {class NewComponent extends PureComponent {constructor(props, context) {super(props);// 将接收到的mapStateToProps赋给state,用于部分值修改时的浅层比较、更新statethis.state = mapStateToProps(context.getState());}componentDidMount() {this.unsubscribe = this.context.subscribe(() => {this.setState(mapStateToProps(this.context.getState()));});}componentWillUnmount() {this.unsubscribe();}render() {// 将接收到的mapStateToProps、mapDispatchToProps传入要返回的新组件中const stateObj = mapStateToProps(this.context.getState());const dispatchObj = mapDispatchToProps(this.context.dispatch);return (<WrapperComponent {...this.props} {...stateObj} {...dispatchObj} />);}}// 在类组件中,通过 contextType 共享store变量NewComponent.contextType = StoreContextreturn NewComponent;};
    }
  4. 最后,在hoc中构建index.js,将优化后的connect导出(hoc/index.js):

    export { StoreContext } from "./StoreContext";
    export { connect } from "./connect";
  5. 在界面中使用现在优化后的connect:

    import React, { PureComponent } from "react";
    import { connect } from "../hoc";
    import { addNumber } from "../store/features/counter";export class About extends PureComponent {render() {const { counter } = this.props;return (<div><h2>About Counter: {counter}</h2></div>);}
    }const mapStateToProps = (state) => ({counter: state.counter.counter,
    });const mapDispatchToProps = (dispatch) => ({addNumber(num) {dispatch(addNumber(num));},
    });export default connect(mapStateToProps, mapDispatchToProps)(About);
  6. 查看效果,与之前效果一致:

在这里插入图片描述

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

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

相关文章

lc1074.元素和为目标值的子矩阵数量

创建二维前缀和数组 两个for循环&#xff0c;外循环表示子矩阵的左上角&#xff08;x1,y1&#xff09;&#xff0c;内循环表示子矩阵的右下角&#xff08;x2,y2&#xff09; 两个for循环遍历&#xff0c;计算子矩阵的元素总和 四个变量&#xff0c;暴力破解的时间复杂度为O(…

ChatGPT安全技术

前言 近期&#xff0c;Twitter 博主 lauriewired 声称他发现了一种新的 ChatGPT"越狱"技术&#xff0c;可以绕过 OpenAI 的审查过滤系统&#xff0c;让 ChatGPT 干坏事&#xff0c;如生成勒索软件、键盘记录器等恶意软件。 他利用了人脑的一种"Typoglycemia&q…

MySQL 5.7版本不支持ROW_NUMBER()函数

MySQL 5.7版本不支持ROW_NUMBER()函数。但是&#xff0c;你可以使用变量来手动实现这个功能。以下是一个示例查询语句&#xff1a; SELECT row_number:row_number1 AS row_num,column1, column2, ... FROM (SELECT row_number:0) AS t,your_table ORDER BY column1;在这个语句…

web3行业有哪些职业发展路径?

Web3 是一个相对较新的概念&#xff0c;因此其职业发展路径也在不断演变。一般来说&#xff0c;Web3 职业发展路径可以分为以下几个方向&#xff1a; 区块链开发工程师&#xff1a;区块链开发工程师需要掌握 Solidity 等语言和智能合约开发技能&#xff0c;负责开发和维护区块…

Vue.js2+Cesium 四、模型对比

Vue.js2Cesium 四、模型对比 Cesium 版本 1.103.0&#xff0c;低版本 Cesium 不支持 Compare 对比功能。 Demo 同一区域的两套模型&#xff0c;实现对比功能 <template><div style"width: 100%; height: 100%;"><divid"cesium-container"…

MTK联发科安卓核心板MT8385(Genio 500)规格参数资料_性能介绍

简介 MT8385安卓核心板 是一个高度集成且功能强大的物联网平台&#xff0c;具有以下主要特性&#xff1a; l 四核 Arm Cortex-A73 处理器 l 四核Arm Cortex-A53处理器 l Arm Mali™-G72 MP3 3D 图形加速器 (GPU)&#xff0c;带有 Vulkan 1.0、OpenGL ES 3.2 和 OpenCL™ 2.x …

tinyproxy搭建http代理

安装tinyproxy yum install tinyproxy 修改配置 vim /etc/tinyproxy/tinyproxy.conf # 允许任意ip访问 Allow 0.0.0.0/0 # 指定端口 ​​​​​​​Port 8888 常用配置 User nobody Group nobody# 绑定监听端口号 Port 8608 # 监听的网络接口 默认会监听所有的接口 #Liste…

Linux中的file命令:查看文件类型

2023年8月1日&#xff0c;周二上午 目录 简要说明使用方法MIME类型举例说明 简要说明 在Linux中&#xff0c;file命令用于识别文件类型。 file命令可以识别各种类型的文件&#xff0c;包括普通文件、目录、符号链接、设备文件、压缩文件、二进制可执行文件等。 它是一个非常…

云原生势不可挡,如何跳离云原生深水区?

云原生是云计算领域一大热词&#xff0c;伴随云原生概念而来的是数字产业迎来井喷、数字变革来临、数字化得以破局以及新一波的技术红利等等。云原生即“云”原生&#xff0c;顾名思义是让“应用”最大程度地利用云的能力&#xff0c;发挥云价值的最佳路径。具体来说&#xff0…

抄写Linux源码(Day2:构建调试环境)

我们计划把操作系统运行在 qemu-system-x86_64 上&#xff0c;使用 gdb 调试 经过 RTFM&#xff0c;可以使用 qemu-system-x86_64 -s -S 让 qemu 在启动之后停住 接着在另一个窗口运行 gdb&#xff0c;输入命令 target remote localhost:1234&#xff0c;即可连接qemu并调试运…

Zookeeper笔记

为什么要使用Zookeeper dubbo需要一个注册中心&#xff0c;而Zookeeper是我们在使用Dubbo是官方推荐的注册中心 Zookeeper介绍 Zookeeper的集群机制 Zookeeper是为了其他分布式程序提供服务的&#xff0c;所以不能随便就挂了。Zookeeper的集群机制采取的是半数存活机制。也…

【MySQL】下载安装以及SQL介绍

1&#xff0c;数据库相关概念 以前我们做系统&#xff0c;数据持久化的存储采用的是文件存储。存储到文件中可以达到系统关闭数据不会丢失的效果&#xff0c;当然文件存储也有它的弊端。 假设在文件中存储以下的数据&#xff1a; 姓名 年龄 性别 住址 张三 23 男 北京…

GitHub基本使用

GitHub搜索 直接搜索 直接搜索关键字 明确搜索仓库标题 语法&#xff1a;in:name [关键词]展示&#xff1a;比如我们想在GitHub仓库中标题中搜索带有SpringBoot关键词的&#xff0c;我们可以样搜: in:name SpringBoot 明确搜索描述 语法&#xff1a;in:description [关键词]展…

常见的锁策略(面试八股文)

1.乐观锁vs悲观锁 乐观锁&#xff1a;预测该场景中不太会出现锁冲突的情况。&#xff08;后续做的工作会更少&#xff09; 悲观锁&#xff1a;预测该场景非常容易出现锁冲突&#xff08;后续做的工作会更多&#xff09; 锁冲突&#xff1a;多个线程同时尝试去获得同一把锁&…

mysql进阶-用户的创建_修改_删除

1. 使用mysql单次查询 [rootVM-4-6-centos /]# mysql -h localhost -P 3306 -p mytest -e "select * from book1"; Enter password: ------------------------------------------- | id | category_id | book_name | num | ----------------------------…

第17节 R语言分析:生物统计数据集 R 编码分析和绘图

生物统计数据集 R 编码分析和绘图 生物统计学,用于对给定文件 data.csv 中的医疗数据应用 R 编码,该文件是患者人口统计数据集,包含有关来自各种祖先谱系的个体的标准信息。 数据集特征解释 脚本 output= file("Output.txt") # File name of output log sink(o…

opencv读取MP4文件和摄像头数据

文章目录 前言一、waitKey函数二、VideoCapture类总结前言 本篇文章来讲解opencv读取MP4文件和摄像头数据,opencv主要用于处理图像数据那么本篇文章就来讲解opencv读取MP4文件和摄像头数据。 一、waitKey函数 waitKey()函数是OpenCV中常用的一个函数,它用于等待用户按键输…

docker常用命令

docker常用命令 1.镜像与容器的关系2. 基本命令3. 容器操作4. 镜像操作5. 文件传输 1.镜像与容器的关系 镜像是类容器是对类实例化的对象 2. 基本命令 启动docker服务systemctl start docker重启docker服务systemctl restart docker 开机自动启动dockersystemctl enable doc…

Spring-mybatis结合的底层原理

1.项目前期准备 1.1 导入maven jar包 <dependencies><!-- spring依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.5.RELEASE</version></depende…

js中的设计模式

设计模式 代码整体的结构会更加清楚&#xff0c;管理起来会更加方便&#xff0c;更好地维护 设计模式是一种思想 发布订阅 模块化开发 导入很多模块 容器即数组存储未来要执行的方法&#xff0c;同addEventListener 数组塌陷问题* 由于删除了元素&#xff0c;导致从删除元素的位…