【解决方案】【最佳实践】React高阶组件中Refs 不会被传递的问题

大家好,我是DX3906。

最近遇到React高阶组件中Refs 不会被传递的问题。

在这里总结一下解决方案和解决思路:主要是通过从内向外从外向内2种思路来分析解决的。

目录

前言

解决方案一:React.forwardRef

解决方案二:使用props传递ref

结语


前言

        虽然高阶组件的约定是将所有 props 传递给被包装组件,但这对于 refs 并不适用。那是因为 ref 实际上并不是一个 prop - 就像 key 一样,它是由 React 专门处理的。如果将 ref 添加到 HOC 的返回组件中,则 ref 引用指向容器组件,而不是被包装组件。

        在React中,Ref是一个React对象,它用于访问DOM节点或组件实例。当你使用高阶组件封装组件时,被封装的组件的Ref可能不会被传递到高阶组件的外部。这是因为高阶组件创建了一个包装组件,它接收原始组件作为prop,并且通常会创建一个新的ref来引用它。

解决方案一:React.forwardRef

        解决这个问题的方法之一是使用React的React.forwardRef函数。forwardRef允许你将一个ref传递给子组件,这样即使组件被高阶组件封装,ref也能正确地传递到最底层的组件。

下面是一个使用React.forwardRef的示例:

import React, { forwardRef } from 'react';

const EnhancedComponent = React.forwardRef((props, ref) => {
  // 将ref传递给被封装的组件
  return <WrappedComponent {...props} forwardedRef={ref} />;
});

const WrappedComponent = forwardRef((props, forwardedRef) => {
  // 使用forwardedRef来访问DOM或组件实例
  return <div ref={forwardedRef}>...</div>;
});

// 使用时,ref将被传递到WrappedComponent的div元素
const ref = React.createRef();
<EnhancedComponent ref={ref} />;

        在这个例子中,EnhancedComponent是一个高阶组件,它使用forwardRef来接收一个ref,并将其传递给WrappedComponentWrappedComponent也使用forwardRef来接收这个ref,并将其应用到内部的DOM元素上。

        使用forwardRef可以确保无论组件被多少层高阶组件封装,ref都能正确地传递到最底层的组件。这使得你可以在需要的时候访问DOM节点或组件实例,而不受高阶组件的影响。

解决方案二:使用props传递ref

    第一步:我们把ref 添加到 HOC 的返回组件中,则 ref 引用指向容器组件,而不是被包装组件。

    第二步:在HOC 把被组装的组件的ref赋值给高阶组件外层的一个instance对象。然后使用第一步中的ref调用instance对象。

        具体案例如下:

function withSubscription(WrappedComponent, selectData) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        data: selectData(props) // 初始状态
      };
      this.instance;
    }

    componentDidMount() {
      // 订阅数据源
      const { subscribe } = this.props;
      subscribe(data => this.setState({ data }));
    }

    componentWillUnmount() {
      // 取消订阅
      const { unsubscribe } = this.props;
      unsubscribe();
    }

    render() {
      // 将数据和原始props传递给WrappedComponent
      return <WrappedComponent ref={(node)=>{this.instance = node}} {...this.props} />;
    }
  };
}
import React,{useEffect,useRef} from "react"
function WithShow(props) {
    let cusRef = useRef(null);
    useEffect(()=>{
        cusRef.current.instance.被包装组件的方法()
    })
    // 使用高阶组件
    const MyComponentWithData = withSubscription(MyComponent, props => {
      // 根据props选择数据
      return someDataSource.getData(props.id);
    });

    // 然后在你的应用中使用MyComponentWithData
    return() {
      // 获取Hoc外层组件的ref
      return <MyComponentWithData ref={cusRef} {...this.props} />;
    }
  };
}

结语

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~ 

  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寻找DX3906

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值