当前位置: 首页 > news >正文

【前端知识】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. 查看效果,与之前效果一致:

在这里插入图片描述

相关文章:

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

React 基础巩固(三十七)——自定义connect高阶组件 一、手撸一个自定义connect高阶组件 import { PureComponent } from "react"; import store from "../store";/*** connect的参数&#xff1a;* 参数一&#xff1a; 函数* 参数二&#xff1a; 函数* 返…...

前端PDF导出,使用html2Canvas和jsPDF插件

import html2Canvas from "html2canvas"; import jsPDF from "jspdf"; export function downloadPDF(dom, filename) {const scale 2;window.pageYOffset 0;// 滚动到顶部&#xff0c;避免打印不全document.documentElement.scrollTop 0;document.body.…...

Android 设备兼容性使用详解

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、设备兼容性分类二、硬件设备兼容三、软件 APP 兼容四、兼容不同语言五、兼容不同分辨率六、兼容不同屏幕方向布局七、兼容不同硬件 Feature八、兼容…...

vnc加固

0x00 认识VNC 先我们看看VNC运行的工作流程&#xff1a; VNC客户端通过浏览器或VNC Viewer连接至VNC Server&#xff1b; VNC Server传送一个对话窗口至客户端&#xff0c;要求输入连接密码&#xff08;可能为空&#xff09;&#xff0c;以及存取的VNC Server显示装置&#…...

Windows下Nginx安装与配置教程

一、前言 1、Nginx是什么&#xff1f; Nginx是一个开源的Web服务器&#xff0c;同时Nginx也提供了反向代理和负载均衡的功能。 Nginx通常作为负载均衡器暴露在外网接受用户请求&#xff0c;同时也使用其反向代理的功能&#xff0c;将用户的请求转发到实际提供服务的内网服务器…...

Iterator迭代器和Generator生成器

Iterator迭代器和for/of循环原理 Iterator迭代器规范 自己创建一个Iterator类,来实现ES6中的迭代器规范: class Iterator {constructor(assemble) {// assemble:需要迭代的数据结构this.assemble = assemble// index:记录迭代的次数(或者索引)this.index = -1}// 必须具…...

Modbus-RTU协议C#实现

1、安装依赖包 System.IO.Ports 2、读协议 /// <summary>/// Modbus-RTU协议读实例/// </summary>private static void Read(){//组装一个请求报文// 01 03 00 00 00 0A C5 CDbyte slave 0x01;//byte function 0x03; //读单个寄存器byte function 0x01; //…...

Redis学习---大数据技术之Redis(NoSQL简介、Redis简介、Redis安装、五大数据类型、相关配置、持久化)

星光下的赶路人star的个人主页 毅力是永久的享受 文章目录 1、NoSQL1.1 NoSQL数据库1.1.1 NoSQL是什么1.1.2 NoSQL的特点1.1.3 NoSQL的适用场景1.1.4 NoSQL的不适场景 1.2 NoSQL家族 2、Redis简介2.1 Redis官网2.2 Redis是什么2.3 Redis的应用场景2.3.1 配合关系型数据库做高速…...

基于组合双向拍卖的共享储能机制研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 2.1 算例数据 2.2 买家中标 2.3 卖家中标 &#x1f389;3 文献来源 &#x1f308;4 Matlab代码实现 &#x1f4a5;1 概述 文献来源&#xff1a; 摘要&#xff1a;为满足共享储能中储能用户的互补性和替代性需求、解决常规单…...

服务机器人有哪些品类

服务机器人是指具备自主运动、感知环境、实现人机交互等能力的机器人&#xff0c;它可以被应用于不同的场景&#xff0c;如餐饮、医疗、物流等行业。根据其功能和应用场景的不同&#xff0c;服务机器人可以分为以下几类&#xff1a;1. 餐饮服务机器人 随着社会发展和人们需…...

3.netty和protobuf

1.ChannelGroup可以免遍历由netty提供,覆盖remove方法即可触发删除channel\ 2.群聊私聊 13.群聊私聊简单原理图 3.netty心跳检测机制,客户端对服务器有没有读写(读,写空闲) //IdleStateHandler(3,5,7,TimeUnite.SECONDS)是netty提供的检测状态的处理器,也加到pipeline,读,写,…...

NLP实践——Llama-2 多轮对话prompt构建

NLP实践——Llama-2 多轮对话prompt构建 1. 问题提出2. prompt的正确形式3. 效果测试4. 结尾 1. 问题提出 最近&#xff0c;META开源了Llama-2模型&#xff0c;受到了广泛的关注和好评&#xff0c;然而&#xff0c;在官方给的使用说明中&#xff0c;并没有对使用方法进行特别细…...

《TCP IP网络编程》第十四章

第 14 章 多播与广播 14.1 多播 多播&#xff08;Multicast&#xff09;方式的数据传输是基于 UDP 完成的。因此 &#xff0c;与 UDP 服务器端/客户端的实现方式非常接近。区别在于&#xff0c;UDP 数据传输以单一目标进行&#xff0c;而多播数据同时传递到加入&#xff08;注…...

网络基础-认识每层的设备和每层的特点用途

目录 网络层次常见设备各层介绍数据链路层网络层传输层应用层 网络层次 常见设备 各层介绍 数据链路层 有了MAC地址。数据链路层工作在局域网中的&#xff0c;以帧为单位进行传输和处理数据。 网络层 网络层有了IP。不同的网络通过路由器连接成为互联网 路由器的功能:   …...

【Linux操作系统】深入解析Linux定时任务调度机制-cronat指令

在Linux操作系统中&#xff0c;定时任务调度是一项重要的功能&#xff0c;它可以让用户在指定的时间或周期性地执行特定的任务。这种机制使得用户能够自动化地执行一些重复性工作&#xff0c;提高工作效率。本文将详细介绍Linux定时任务调度的原理、常用指令和代码示例&#xf…...

动手学深度学习(一)预备知识

目录 一、数据操作 1. N维数组样例 2. 访问元素 3. 基础函数 &#xff08;1&#xff09; 创建一个行向量 &#xff08;2&#xff09;通过张量的shape属性来访问张量的形状和元素总数 &#xff08;3&#xff09;reshape()函数 &#xff08;4&#xff09;创建全0、全1、…...

item_get-KS-获取商品详情

一、接口参数说明&#xff1a; item_get-根据ID取商品详情 &#xff0c;点击更多API调试&#xff0c;请移步注册API账号点击获取测试key和secret 公共参数 请求地址: https://api-gw.onebound.cn/ks/item_get 名称类型必须描述keyString是调用key&#xff08;http://o0b.cn/…...

[华为OD] 最小传输时延(dijkstra算法)

明天就要面试了我也太紧张了吧 但是终于找到了一个比较好理解的dijkstra的python解法&#xff0c;让我快点把它背下来&#xff01;&#xff01;&#xff01;&#xff01; 文章目录 题目dijkstra算法的python实现python解答dfs解法dijkstra解法 题目 先把题目放出来 某通信网络…...

问道管理:总资产大于总市值好吗?

在财政领域&#xff0c;总财物和总市值是两个非常重要的指标。总财物是指公司所有的财物&#xff0c;包括固定财物、流动财物、无形财物等&#xff0c;而总市值则是指公司股票在商场上的总价值。当总财物大于总市值时&#xff0c;这是否是一个好的信号呢&#xff1f;咱们将从多…...

IBM Spectrum LSF (“LSF“ ,简称为负载共享设施) 用户案例

IBM Spectrum LSF (“LSF” &#xff0c;简称为负载共享设施) 用户案例 IBM Spectrum LSF (“LSF” &#xff0c;简称为负载共享设施) 软件是业界领先的企业级软件。 LSF 在现有异构 IT 资源之间分配工作&#xff0c;以创建共享&#xff0c;可扩展且容错的基础架构&#xff0c…...

华为交换机Telnet配置保姆级教程:从无认证到AAA认证,手把手带你避坑

华为交换机Telnet安全配置全指南&#xff1a;从基础到企业级实践 远程管理网络设备是每位网络工程师的必备技能&#xff0c;而Telnet作为最传统的远程登录协议之一&#xff0c;至今仍在许多企业环境中广泛使用。记得我刚入行时&#xff0c;第一次通过Telnet成功登录到一台核心交…...

保姆级教程:在Ubuntu 22.04上从源码编译RISC-V SPIKE模拟器(含libboost报错解决)

从零构建RISC-V开发环境&#xff1a;Ubuntu 22.04下SPIKE模拟器深度编译指南 当第一次接触RISC-V生态时&#xff0c;搭建可靠的开发环境往往成为新手面临的第一个挑战。作为RISC-V官方推荐的指令集模拟器&#xff0c;SPIKE以其轻量级和准确性成为学习RISC-V架构的理想工具。本文…...

NotebookLM默认α=0.05合理吗?(基于127个真实知识图谱实验的P值稳健性评估报告)

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;NotebookLM默认α0.05合理吗&#xff1f;&#xff08;基于127个真实知识图谱实验的P值稳健性评估报告&#xff09; 在NotebookLM的知识图谱推理链中&#xff0c;显著性阈值α被硬编码为0.05&#xff0c;该设定…...

音乐解锁神器:3种方法让加密音乐重获自由

音乐解锁神器&#xff1a;3种方法让加密音乐重获自由 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地址: https://gitcode.c…...

Windows热键冲突终结者:Hotkey Detective一键定位占用程序

Windows热键冲突终结者&#xff1a;Hotkey Detective一键定位占用程序 【免费下载链接】hotkey-detective A small program for investigating stolen key combinations under Windows 7 and later. 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective 你是…...

轻量级本地OCR工具SmolDocling实战指南

1. 项目概述&#xff1a;为什么需要一个本地运行的轻量级OCR应用&#xff1f;SmolDocling这个名字本身就带着点工程师式的幽默感——“smol”是“small”的网络变体&#xff0c;强调体积小、依赖少&#xff1b;“Docling”则暗指文档&#xff08;document&#xff09;处理的小精…...

抖音资源下载新体验:douyin-downloader一站式解决方案

抖音资源下载新体验&#xff1a;douyin-downloader一站式解决方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback suppo…...

[特殊字符]LeetCode每日一题思维训练234.回文链表|拒绝无脑AC,练会核心思维(2026-5-21)

刷LeetCode最扎心的不是做不出来&#xff0c;而是AC了却没get核心思路&#xff0c;面试换个变体就直接懵圈&#xff0c;白刷一场&#xff01; &#x1f449; 每日一题思维训练 ✨ 它和普通题解工具不一样&#xff1a;不直接甩答案&#xff0c;只引导你主动思考&#xff01; 精…...

NotebookLM落地失败真相:为什么83%团队卡在第2阶段?3个权威诊断指标立即自检

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;NotebookLM落地失败的核心归因诊断 NotebookLM 作为 Google 推出的面向文档理解的实验性 AI 工具&#xff0c;其本地化部署与企业级集成常遭遇系统性失效。深入分析表明&#xff0c;失败并非源于单一技术缺陷…...

java之微信机器人二次开发文档

WTAPI框架weixin ipad 协议 在微信个人号二次开发中的应用&#xff0c;涵盖技术架构、核心功能、开发流程及安全合规要点&#xff0c;为开发者提供系统化解决方案。 ⚡ 核心能力 好友管理&#xff1a;添加好友、删除好友、修改备注、创建标签、获取好友列表、搜索好友信息 消息…...