我的编程空间,编程开发者的网络收藏夹
学习永远不晚

ReactRefs转发实现流程详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

ReactRefs转发实现流程详解

Refs转发

概述

  • 将ref自动地通过组件传递到子组件的技巧
  • 父组件可以通过ref操作子组件,直接使用子组件的DOM

转发refs到DOM组件

渲染原生 DOM 元素 button 的 FancyButton 组件(子组件)

function FancyButton(props) {
  return (
    <button className="FancyButton">
      {props.children}
    </button>
  )
}

Ref 转发是一个可选特性,其允许某些组件接收 ref,并将其向下传递给子组件

//子组件
const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
))
//父组件
//可以直接获取 DOM button 的 ref:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
//这样,在父组件中可以直接使用DOM button

以下是对上述示例发生情况的逐步解释:

  • 通过调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量
  • 指定 ref 为 JSX 属性,将其向下传递给 FancyButton React
  • 传递ref给forwardRef作为其第二个参数
  • 向下转发ref参数到button,并将其指定为JSX属性
  • 当ref挂载完成,ref.current将指向button DOM节点

组件库维护者的注意事项

当使用forwardRf时,应将其视为一个新的主版本

在高阶组件中转发refs

转发ref对高阶组件是很有用的,让我们从一个输出组件props到控制台的高阶组件为例

 function logProps(WrappedComponent) {
   class LogProps extends React.Component {
     componentDidUpdate(prevProps) {
       console.log('old props:', prevProps);
       console.log('new props:', this.props);
     }
     render() {
       return <WrappedComponent {...this.props} />;
     }
   }
   return LogProps;
 }

logProps组件是一个高阶组件,props将会传递到其包裹的组件。这个高阶组件可以记录所有传递到fancyButton组件的props

class FancyButton extends React.Component {
     focus() {
       // ...
     }
     // ...
}
   // 我们导出 LogProps,而不是 FancyButton。
   // 虽然它也会渲染一个 FancyButton。
   export default logProps(FancyButton)

需要注意:refs 将不会透传下去。这是因为 ref 不是 prop 属性。就像 key 一样,其被 React 进行了特殊处理

如果对 HOC 添加 ref,该 ref 将引用最外层的容器组件,而不是被包裹的组件

意味着用于我们 FancyButton 组件的 refs 实际上将被挂载到 LogProps 组件

   import FancyButton from './FancyButton';
   const ref = React.createRef();
   // 我们导入的 FancyButton 组件是高阶组件(HOC)LogProps。
   // 尽管渲染结果将是一样的,
   // 但我们的 ref 将指向 LogProps 而不是内部的 FancyButton 组件!
   // 这意味着我们不能调用例如 ref.current.focus() 这样的方法
   <FancyButton
     label="Click Me"
     handleClick={handleClick}
     ref={ref}
   />;

解决办法:可以使用 React.forwardRef API 明确地将 refs 转发到内部的 FancyButton 组件。React.forwardRef 接受一个渲染函数,其接收 props 和 ref 参数并返回一个 React 节点

function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }
    render() {
      const {forwardedRef, ...rest} = this.props;

      // 将自定义的 prop 属性 “forwardedRef” 定义为 ref
      return <Component ref={forwardedRef} {...rest} />;
    }
  }
  // 注意 React.forwardRef 回调的第二个参数 “ref”。
  // 我们可以将其作为常规 prop 属性传递给 LogProps,例如 “forwardedRef”
  // 然后它就可以被挂载到被 LogProps 包裹的子组件上。
  return React.forwardRef((props, ref) => {
    return <LogProps {...props} forwardedRef={ref} />;
  });
}

在 DevTools 中显示自定义名称

下面的组件将在DevTools中显示为“ForwardRef”

const WrappedComponent = React.forwardRef((props, ref) => {
  return <LogProps {...props} forwardedRef={ref} />;
})

如果命名了渲染函数,DevTools 也将包含其名称(例如 “ForwardRef(myFunction)”)

const WrappedComponent = React.forwardRef(
  function myFunction(props, ref) {
    return <LogProps {...props} forwardedRef={ref} />;
  }
)

设置函数的 displayName 属性来包含被包裹组件的名称

function logProps(Component) {
  class LogProps extends React.Component {
    // ...
  }
  function forwardRef(props, ref) {
    return <LogProps {...props} forwardedRef={ref} />;
  }
  // 在 DevTools 中为该组件提供一个更有用的显示名。
  // 例如 “ForwardRef(logProps(MyComponent))”
  const name = Component.displayName || Component.name;
  forwardRef.displayName = `logProps(${name})`;
  return React.forwardRef(forwardRef);
}

到此这篇关于React Refs转发实现流程详解的文章就介绍到这了,更多相关React Refs转发内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

ReactRefs转发实现流程详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

ReactRefs转发实现流程详解

Refs是一个获取DOM节点或React元素实例的工具,在React中Refs提供了一种方式,允许用户访问DOM节点或者在render方法中创建的React元素,这篇文章主要给大家介绍了关于React中refs的一些常见用法,需要的朋友可以参考下
2022-12-03

KotlinstartActivity跳转Activity实现流程详解

在Android当中,Activity的跳转有两种方法,第一个是利用startActivity(Intentintent);的方法,第二个则是利用startActivityForResult(Intentintent,intrequestCode);的方法,从字面上来看,这两者之间的差别只在于是否有返回值的区别,实际上也确实只有这两种区别
2022-12-08

Python实现JavaBeans流程详解

这篇文章主要介绍了Python实现JavaBeans流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2023-01-14

使用JetpackCompose实现翻转卡片效果流程详解

JetpackCompose是一款基于Kotlin的声明式UI工具包,可以方便地创建漂亮的用户界面。使用Compose的动画API和可绘制API,可以轻松实现翻转卡片效果。通过设置旋转角度和透明度等属性,可以使卡片沿着Y轴翻转,并实现翻页效果
2023-05-19

Kotlin使用协程实现高效并发程序流程详解

这篇文章主要介绍了Kotlin使用协程实现高效并发程序流程,协程属于Kotlin中非常有特色的一项技术,因为大部分编程语言中是没有协程这个概念的。那么什么是协程呢?它其实和线程有点相似,可以简单地将它理解成一种轻量级的线程
2023-01-18

Vuereactive函数实现流程详解

一个基本类型的数据,想要变成响应式数据,那么需要通过ref函数包裹,而如果是一个对象的话,那么需要使用reactive函数,这篇文章主要介绍了Vuereactive函数
2023-01-04

Java使用跳转结构实现队列和栈流程详解

这篇文章主要介绍了Java使用跳转结构实现队列和栈流程,连续结构和跳转结构是数据结构中常见的两种基本数据结构,而我们本次的主角栈和队列都既可以使用使用跳转结构实现也可以使用连续结构实现
2023-05-15

详解Android USB转串口通信开发基本流程

好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信,一直忙到最近,才慢慢闲下来,趁着这个周末不忙,记录下usb转串口通信开发的基本流程。 我们开发使用的是usb主机模式
2022-06-06

C++模拟实现vector流程详解

这篇文章主要介绍了C++容器Vector的模拟实现,Vector是一个能够存放任意类型的动态数组,有点类似数组,是一个连续地址空间,下文更多详细内容的介绍,需要的小伙伴可以参考一下
2022-11-13

详解Java实现简单SPI流程

这篇文章主要介绍了Java实现简单SPI流程,SPI英文全称为ServiceProviderInterface,顾名思义,服务提供者接口,它是jdk提供给“服务提供厂商”或者“插件开发者”使用的接口
2023-03-02

Mybatis实现SQL存储流程详解

MyBatis作为一款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。它免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作
2023-03-10

Android 开发订单流程view实例详解

Android 开发订单流程view实例详解 先看看最终效果图:怎么样,效果还是很不错的吧?群里有人说切四张图的、recycleview的、各种的都有啊,但是最简单的就是通过自定义view来实现了~接下来让我们来实现下这个(订单流程vie
2022-06-06

编程热搜

目录