惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Microsoft Security Blog
Microsoft Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
V
Visual Studio Blog
宝玉的分享
宝玉的分享
IT之家
IT之家
人人都是产品经理
人人都是产品经理
T
The Blog of Author Tim Ferriss
I
InfoQ
B
Blog RSS Feed
T
Threatpost
博客园_首页
M
MIT News - Artificial intelligence
Spread Privacy
Spread Privacy
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Know Your Adversary
Know Your Adversary
U
Unit 42
Engineering at Meta
Engineering at Meta
C
Cyber Attacks, Cyber Crime and Cyber Security
月光博客
月光博客
Scott Helme
Scott Helme
T
Tor Project blog
有赞技术团队
有赞技术团队
AWS News Blog
AWS News Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Last Week in AI
Last Week in AI
S
Schneier on Security
Vercel News
Vercel News
博客园 - Franky
C
Cybersecurity and Infrastructure Security Agency CISA
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
L
LangChain Blog
爱范儿
爱范儿
Google DeepMind News
Google DeepMind News
The GitHub Blog
The GitHub Blog
雷峰网
雷峰网
Latest news
Latest news
C
CXSECURITY Database RSS Feed - CXSecurity.com
Hugging Face - Blog
Hugging Face - Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
S
Security Affairs
A
About on SuperTechFans
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
大猫的无限游戏
大猫的无限游戏
W
WeLiveSecurity
Cisco Talos Blog
Cisco Talos Blog
罗磊的独立博客

逐梦个人博客

使用原生JS监听浏览器的前进后退事件-逐梦个人博客 微信小程序中使用微信头像的实现方式-逐梦个人博客 如何在WebWorker中使用psd.js-逐梦个人博客 如何根据权重裁剪FaceApi.js返回的人脸数据-逐梦个人博客 在WebWorker中使用FaceAPI.js的正确姿势-逐梦个人博客 解锁React组件函数this绑定新方式-逐梦个人博客 关于照片Exif Orientation信息的处理-逐梦个人博客 防止其他网站通过iframe嵌套自己站点的两种方式-逐梦个人博客 警惕!wordpress站长必知的重大安全漏洞合集-逐梦个人博客
React通用带上下文的组件ID实现方案-逐梦个人博客
Dean · 2023-06-15 · via 逐梦个人博客

使用React开发我们会根据需求定义各种组件,然后将组件做一定的组合/嵌套最终实现需求,在这个过程中就会经常出现这么一种情况:

假设现在有CompA,CompB,CompC三个组件,其中CompA和CompB都使用了CompC组件,现需要对CompC中的某个方法做埋点,如何确定该方法是在CompA下调用的,还是在CompB下调用的呢?

可能有些朋友会说可以通过传参来实现,CompA和CompB分别向CompC传递一个参数/标志,这种方式确实可以做到,但是实际使用却并不合理,因为组件的嵌套层级可能很深,如果通过参数一级一级传递,容易出错还不太好维护,仅仅是为了一个简单的埋点参数,有点浪费。有没有什么更好的方法呢?

一、实现

如果CompA下的CompC可获得标识CompA.CompC,CompB下的CompC可获得标识CompB.CompC, 以此类推:CompA.CompC.CompDCompB.CompC.CompD,通过这个标识就可以识别出组件使用的上下文,进而更容易调查问题的根源,现在问题变成了如何让组件自身携带上下文的ID,因为组件的嵌套层级不确定,为了更好的传递这个ID,我的第一反应是使用嵌套的context,大家都知道context允许跨层级传递数据,在一番实验后,得到了以下高阶组件:

import React from 'react';
import PropTypes from 'prop-types';

function WithComponentId(WrappedComponent, definedComponentId) {
  class Component extends React.Component {
    static childContextTypes = {
      componentId: PropTypes.string,
    };

    static contextTypes = {
      componentId: PropTypes.string,
    };

    constructor(props) {
      super(props);

      this.getComponentId = this.getComponentId.bind(this);
    }

    getChildContext() {
      const componentId = this.getComponentId();
      return {
        componentId,
      };
    }

    getComponentId() {
      const componentId = definedComponentId || WrappedComponent.name;
      if (this.context) {
        const { componentId: parentComponentId } = this.context;
        return `${parentComponentId ? parentComponentId : ''}.${componentId ? componentId : ''}`.replace(/(^\.+|\.+$)/g, '');
      }
      return componentId;
    }

    render() {
      return (
        <WrappedComponent {...this.props} getComponentId={this.getComponentId}/>
      )
    }
  }
  return Component;
}

export default WithComponentId;

上面的高阶组件接受上层context传递的组件Id并拼装新的上下文组件ID利用context传递下去,该组件接收一个组件和一个标识ID(可选)作为参数,通过context获取到上层组件的componentId并和当前传入组件的componentId进行组合拼装,得到一个新的带上下文的组件ID并利用context传递给传入组件及其子孙组件,同时向传入组件传递一个getComponentId方法用于获取带上下文的组件ID。

使用的时候仅需用上面的高阶组件包装一下目标组件即可,类似下面:

export default WithComponentId(CompA, 'CompA');
export default WithComponentId(CompB, 'CompB');
export default WithComponentId(CompC, 'CompC');
export default WithComponentId(CompD, 'CompD');

如果不传入组件ID会以传入组件的名称作为组件ID。组件包装完成后,我们就可以在任何通过高阶组件包装了的组件中通过getComponentId方法获取带上下文的组件ID并使用。

二、结语

在上面的高阶组件中,我们选择了使用context来跨层级传递数据,主要是考虑一个大的组件树中有可能部分中间态组件并不需要组件ID,但是我们又需要保证上层组件ID的传递,而且这种方式对于已有项目进行改造是比较合理的,我们只需要通过高阶组件包装我们关心的组件即可,而不需要每个组件都改到,那意味着巨大的工作量。当然对于新项目来说,如果最初的想法就是每个组件都有自己的组件ID,我们也可以在高阶组件中通过属性传值的方式来实现。