一次性搞定React的Ref功能

React useEffect Hook:副作用处理、依赖数组与性能优化 在React函数组件开发中,副作用处理是核心挑战之一。副作用指组件渲染流程之外与外部世界的交互操作,如数据获取、DOM操作、事件订阅等。React通过useEffect Hook提供声明式副作用管理机制,其原理基于React的渲染与提交阶段分离模型,确保副作用在DOM更新后安全执行。该机制的技术价值在于实现副作用逻辑与渲染逻辑的解耦,提升代码可维护性。应用场景涵盖组件挂载/卸载、状态/属性变化响应、DOM同步操作等。本文聚焦useEffect的依赖数组机制、四种经典使用模式,并针对无限循环、过时闭包等常见陷 阅读详情

1.String Ref

String Ref是个过时的API。因为String类型的Ref存在一些问题,将在未来的某个版本中被遗弃,不建议使用。

使用方式:this.refs.XXX获取DOM元素节点:

获取普通标签:

import React, { Component } from 'react';
class App extends Component {
    componentDidMount() {
        console.log('this.refs.XXX');
        console.log(this.refs.h1Ref);
    }
    render() {
        return <h1 ref='h1Ref'>Hello World!</h1>
    }
}
export default App;

复制代码打印结果:

 this.refs.xxx
 <h1>Hello World!</h1>

获取react组件:此时可以调用组件上的方法

import React, { Component } from 'react';
class App extends Component {
    componentDidMount() {
        console.log(this.refs.childRef);
        this.refs.childRef.handleLog(); // Child Component    }
    render() {
        return (
            <div>
                <h1>Hello World!</h1>
                <Child ref='childRef' count='1' />
            </div>
        )
    }
}
class Child extends Component {
    handleLog = () => {
        console.log('Child Component');
    }
    render() {
        const { count } = this.props;
        return <h2>count: { count }</h2>
    }
}
export default App;

// 结果
组件的引用,包括上面挂载的函数和组件props等

2.Callback Ref

Callback Ref能助你更精细地控制何时 refs

被设置和解除,传递一个函数。这个函数中接受 React 组件实例或 HTML DOM 元素作为参数。

React 将在组件挂载时,会调用 ref 回调函数并传入 DOM 元素,当卸载时调用它并传入 null。在 componentDidMount 或 componentDidUpdate 触发前,React 会保证 refs 一定是最新的。

使用方式:ref={element => (this.eleRef = element)}

获取DOM元素节点:

import React, { Component } from "react";
class App extends Component {
  componentDidMount() {
    console.log("Callback Ref");
    console.log(this.h1Ref);
  }
  render() {
    return (
      <div>
        <h1 ref={element => (this.h1Ref = element)}>Hello World!</h1>
      </div>
    );
  }
}
export default App;

// 打印结果
 Callback Ref
 <h1>Hello World!</h1>

获取子组件实例:【同上可调用方法】

import React, { Component } from "react";
class App extends Component {
  componentDidMount() {
    console.log("Callback Ref");
    console.log(this.childRef);
    this.childRef.handleLog();
  }
  render() {
    return (
      <div>
        <h1>Hello World!</h1>
        <Child ref={component => (this.childRef = component)} count="1" />
      </div>
    );
  }
}
class Child extends Component {
  handleLog = () => {
    console.log("Child Component");
  };
  render() {
    const { props } = this;
    return <h1>count: {props.count}</h1>;
  }
}
export default App;

3.Create Ref

该功能是React16.3中发布的,并且在类组件中推荐使用

使用React.createRef()创建Refs,通过ref附加到组件中,对该节点的引用通过ref的current属性访问

React在组件挂载时给current传入DOM元素,并在组件卸载时传入null,ref会在生命周期函数前更新完成

使用方法和前两种类似,这里就不一一列举了

import React, { Component, createRef} from "react";
class App extends Component {
  constructor(props) {
    super(props);
    this.h1Ref = createRef();
  }
  componentDidMount() {
    console.log("React.createRef()");
    console.log(this.h1Ref.current);
  }
  render() {
    return <h1 ref={this.h1Ref}>Hello World!</h1>;
  }
}
export default App;

4.useRef

当在函数组件中使用前三种ref,会抛出以下错误:Uncaught Invariant Violation: Function components cannot have refs. Did you mean to use React.forwardRef()?

原因:函数组件和class组件根本区别是,函数组件没有实例,所以无法使用实例对象,取而代之的为useRef,或使用forwardRef

作用:

  • 获取DOM节点
  • 获取组件实例
  • 渲染周期之间共享数据存储(state修改会触发重新渲染,所以不能跨周期共享)

使用方法:与createRef类似,挂在current上

import React, { useEffect, useRef } from 'react';
function App() {
  const h1Ref = useRef();
  useEffect(() => {
    console.log('useRef')
    console.log(h1Ref.current)
  }, [])
  return <h1 ref={h1Ref}>Hello World!</h1>
}
export default App;

5 不同渲染周期之间的数据共享

该情况主要解决一类问题:类组件中,函数组件中的属性无法跨渲染周期进行数据共享,因为每次保存都会刷新数据重新渲染

示例程序:(其中的timer无法跨渲染周期,每次执行App函数,其都会被重置)

import React, { useState, useEffect, useRef } from "react";
function App() {
  const [count, setCount] = useState(0);
  // 把定时器设置成全局变量使用useRef挂载到current上
  const timer = useRef();
  // const timer; // 这种会导致每次timer都是新的
  // 首次加载useEffect方法执行一次设置定时器
  useEffect(() => {
    timer.current = setInterval(() => {
      setCount(count => count + 1); // 此处必须传入函数,否则拿到的都是组将挂载时的初值!!
    }, 1000);
  }, []);
  // count每次更新都会执行这个副作用,当count > 5时,清除定时器
  useEffect(() => {
    if (count > 5) {
      clearInterval(timer.current);
    }
  });
  return <h1>count: {count}</h1>;
}
export default App;

6 各方式使用总结

ref方式定义获取元素引用执行挂载在元素内的函数备注
string ref标签内ref=‘xxx’this.refs.xxxthis.refs.xxx.handle()已过时
callback ref标签内ref={(element)=>{this.xxx=element}}this.xxxthis.xxx.handle()精准控制ref
create ref构造中this.xxx=createRef() 标签中ref={this.xxx}this.xxx.currentthis.xxx.current.handle()推荐使用
useRef()函数组件中const 函数标签中xxx=useRef() ref={xxx}xxx.currentxxx.current.handle()函数组件中的ref替代方法

【参考】
https://juejin.im/post/5d67d41e5188254628237485

7 Ref转发

有时候需要传递ref给子组件,需要用到React.forwardRef函数,因为常规函数组件和 class 组件不接收 ref 参数,且 props 中也不存在 ref。

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// 你可以直接获取 DOM button 的 ref:
const ref = React.createRef();
// 此时的ref即React.forwardRef的参数之一
<FancyButton ref={ref}>Click me!</FancyButton>;

这个例子展示了,将ref转发到了最终的button标签上,其实Ref 转发不仅限于 DOM 组件,你也可以转发 refs 到 class 组件实例中。

HOC Ref转发

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} />;
  });
}

这时候logProps如何调用,目前没搞懂,怎么同时把Component和ref传进去
猜测:

const Test = logProps(<button>123</button>)
const ref = React.createRef()
<Test ref={ref}/>
React渲染数组核心原理:map、key与Fragment深度解析 在React中,数组渲染并非简单的语法操作,而是触发虚拟DOM比对、影响组件复用与状态绑定的关键环节。其底层依赖reconciler协调算法,核心围绕map生成合法React Element、key提供稳定节点标识、Fragment保持DOM语义纯净三大机制展开。掌握这些原理,可避免90%以上的列表错乱、性能抖动与无障碍缺陷,广泛应用于TodoList、用户管理、表格渲染等高频场景。本文聚焦render arrays实践本质,结合key和fragment真实工程约束,提供可落地的性能优化与错误排查路径。 阅读详情

相关推荐

别再手动改JSON字段名了!用ABAP的/ui2/cl_json和name_mappings,5分钟搞定大小写、驼峰映射

本文详细介绍了如何利用ABAP的/ui2/cl_json类和name_mappings功能,快速解决JSON字段名的大小写和驼峰命名转换问题。通过实战示例和高级技巧,帮助开发者优雅处理SAP与外部系统集成时的命名规范冲突,大幅提升开发效率和代码可维护性。

weixin_30832405的博客 420

React Spring 核心原理:用弹簧物理模型解决状态与动画同步断层

在 React 动画开发中,'状态更新异步性'与'动画时间轴确定性'的矛盾长期存在,导致 CSS 过渡、react-transition-group 等方案频繁出现卸载警告、内存泄漏或视觉错位。React Spring 以胡克定律(F = -kx)为底层建模基础,将 opacity、transform 等样式属性转化为可订阅的连续状态流,通过 tension、damping、mass 等物理参数控制收敛过程,使动画成为状态的渐进式表达而非副作用。这种设计天然契合 React 协调机制,在表单加载态、列表增删

搜索 514

VSCode关联VIVADO编辑Verilog

有时候接手别人的代码,或者从网上找的开源代码,每个人风格不一致,对齐缩进也不一样,阅读起来很累。有没有什么方法能快捷地格式化代码呢。下面我们利用VSCode插件来实现这个需求。Vivado是Xilinx公司提供的逻辑开发平台(之一),如果不喜欢Vivado自带的文本编辑器,可以选择第三方的文本编辑器VSCode。

小王在努力...的博客 7150

react动态绑定ref

【代码】react动态绑定ref。

臧小川的博客 1453

HTTP 代理服务器的设计与实现

HTTP 代理服务器的设计与实现 首先当然是最重要的代码:github地址 1) 实验目的 熟悉并掌握 Socket 网络编程的过程与技术;深入理解 HTTP 协议,掌握 HTTP 代理服 务器的基本工作原理;掌握 HTTP 代理服务器设计与编程实现的基本技能。 2) 实验内容 基于 java 实现了基本功能与全部附加功能,并增加了 https 的支持 (1) 设计并实现一个基本 HTTP 代理服...

qq_42754642的博客 1887

别再手动对照了!用Python+ArcGIS Pro一键搞定三调数据转土地三大类

本文介绍如何利用Python和ArcGIS Pro实现三调数据向土地三大类的自动化转换,大幅提升国土空间规划和土地变更调查的工作效率。通过封装分类规则为Python函数并集成到ArcGIS Pro脚本工具中,解决了传统手动操作耗时且易错的问题,适用于大规模数据处理场景。

weixin_29081101的博客 304

React createRef循环动态赋值ref

handleChange = (key) => { this[`input${key}Ref`] = React.createRef(); } handleSave = () => { const { list } = this.state; for (let item of list) { if (item.value && item.value.length > 100) { Toast.show(`${i.

weixin_47292253的博客 4243

【Unity+HoloLens2】从0开始在HoloLens2部署MR工程

HoloLens2部署的权威教程在微软的官方文档中,但有些问题其实官方文档并没有列出,所以在实际开发过程中如果遇到bug,就需要自身或者前人的经验去解决。比如:对于Hololens2来说,在VS中需选择ARM64而不是x86。部署需要有良好的网速;工程打包出来的文件路径和工程路径有关联,如果这两个路径不匹配,部署就会失败。部署后打不开可能是因为Unity中未添加需要部署的场景,在Build Settings中点击Add open Scenes。...

fmxs 4571

React中如何使用ref

React如何使用ref

qq_45149366的博客 2447

Ubuntu22.04 网络图标消失与连接故障排查指南(附实战修复流程)

本文详细介绍了Ubuntu22.04系统中网络图标消失与连接故障的排查与修复方法。通过ifconfig、dhclient等命令诊断问题,提供从紧急恢复网络连接到深度排查的完整解决方案,帮助用户快速恢复网络功能并预防类似问题再次发生。

weixin_28481133的博客 287

YOLOv8改进,YOLOv8添加DCNv4可变性卷积(windows系统成功编译),全网最详细教程

DCNv4通过两项关键增强解决了其前身DCNv3的局限性:1. 移除空间聚合中的softmax归一化,以增强其动态特性和表达能力;2. 优化内存访问以最小化冗余操作,从而加速计算。这些改进使得DCNv4相比DCNv3显著加快了收敛速度,并且处理速度大幅提升,前向传播速度超过三倍。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 6469

react中动态生成ref进行操作

import { useRef, useState,useEffect } from 'react'; import './Seven.scss'; import gof from './imgs/sevenbj.png' function Seven() { const [sss, setsss] = useState(9) const refs = [] //存储ref的数组 const [ren, setRen] = useState([ { .

皮蛋solo粥的博客 2570

Unity 工具 之 SoftMask软遮罩 实现 UI 边缘渐变过渡的简单使用介绍

目录Unity 工具 之 SoftMask软遮罩 实现 UI 边缘渐变过渡的简单使用介绍一、简单介绍二、Mask 实现的遮罩效果三、Soft Mask 实现遮罩效果四、 Soft Mask 的一些设置五、插件下载Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。

仙魁XAN 8575

React将子组件的ref传给父组件的俩种方法

文章目录父组件如何获得子组件的Ref笔者给大家提供俩种方法:一:使用React.forwardRef二:在子组件初始化的时候将ref通过事件传递给父组件 父组件如何获得子组件的Ref 在我们实际开发的过程当中难免会遇到父组件想要获得子组件的ref进行一些操作的时候,那么我们怎么做呢? 笔者给大家提供俩种方法: 一:使用React.forwardRef 这是react官方文档中给我们说明的,我们照着...

吴小迪的博客 2万+

PLC框架-1.3- 汇川PN伺服(3号报文)

本文以汇川IS620F伺服为例,详细介绍了FB_Servo_ToAxis功能块的应用方法。该功能块封装了MC_Home等轴控指令,实现使能、定位、点动、速度模式及回零等功能,支持转矩限制与显示,并具备行程统计和HMI单位自动切换特性。文章从硬件配置(PN网络连接、报文选择)、参数设置(控制模式、电子齿轮比),到软件实现(功能块调用、手动/自动控制逻辑)进行了系统说明,重点展示了绝对/相对定位、速度模式等典型应用场景的程序编写方法,为汇川伺服在Profinet网络下的工程应用提供了完整解决方案。

qq_34047402的博客 756

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

React访问input内容,不使用onChange方法

React访问input标签内容 很常用的需求,在react的某个方法中需要访问render到页面上的某个input,有几种方法,这里介绍一种最简单的方法(类似html中的getElementById): ref 使用隐藏熟悉ref,指定ref的值,即可以在组件中任何地方获取该标签对象: render的return中返回: <form onSubmit={this.submitHandle...

xiaopi3的博客 1365

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

React定时器开发常见8个坑与解决方案:如何用react-timer-hook构建可靠不掉拍的计时器

在 **React 定时器**开发中,倒计时、秒表和时间显示是最常见的需求之一,但手写 `setInterval` 的逻辑很容易踩中**状态漂移、内存泄漏、节拍错位**这些隐形陷阱。开源库 **react-timer-hook** 是一个轻量级 React 计时器 Hook,把 `useTimer`(倒计时)、`useStopwatch`(秒表)、`useTime`(当前时间)三大 Hook 封装

gitblog_00357的博客 400

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

React Navigation 5 + Ignite Bowser:构建多层级导航系统的完整指南

**Ignite Bowser** 是 Infinite Red 团队推出的 React Native 模板,内置 **React Navigation 5** 双层导航架构。本文将从零带新手搭建多层级导航系统:理解 Root Navigator 与 Primary Navigator 的分层思想、添加新页面路由、处理 Android 返回键和导航状态持久化。学完即可动手构建自己的跨平台 App

gitblog_00368的博客 362

如何打造优雅的滚动进场动画:React LazyShow 组件的 IntersectionObserver + Framer Motion 完整原理

**react-landing-page-template-2021** 是一款即插即用的 React / Next.js 着陆页模板,它的页面之所以滚动起来赏心悦目,秘诀在于一个叫 **LazyShow** 的轻量子组件——它用浏览器原生的 **IntersectionObserver** API 做"元素是否进入视口"的检测,再交给 **Framer Motion** 库驱动进场动画。本文带你

gitblog_01143的博客 441

React平滑滚动实现原理与自定义Hook实战

平滑滚动是现代Web应用的基础交互体验,其本质是浏览器原生滚动API与DOM布局计算的协同过程。理解scrollIntoView、getBoundingClientRect及滚动上下文(scrolling container)的工作原理,是解决固定头部遮挡、路由跳转失效、移动端兼容性等核心问题的前提。在React中,还需深度对齐组件生命周期——useLayoutEffect确保DOM就绪,Ref绑定保障节点可访问,而自定义Hook封装则将行为控制、偏移校准(offsetY)、Safari降级等工程细节收敛为

weixin_30756499的博客 760

React 中正确集成 Font Awesome 5 的完整实践指南

Font Awesome 是前端最主流的 SVG 图标库之一,其核心价值在于提供标准化、可定制、高兼容性的矢量图标资源。在 React 这类声明式、组件化框架中,直接引入 CDN 或使用 class 触发伪元素会破坏虚拟 DOM 一致性,引发 hydration mismatch、FOUC、SSR 失败等问题。真正可靠的集成方式是采用官方 `@fortawesome/react-fontawesome` 包——它通过纯 React 组件封装、按需导入(Tree-shaking)、图标注册中心与 SSR 友好

cnracht8153的博客 399

一文搞定前端项目所用技术

uni-app 是一个使用 Vue.js 语法开发前端应用的框架。它的核心优势是。开发者编写一套代码后,可以将其编译发布到 iOS、Android、Web(H5)、以及各种主流小程序(微信、支付宝、抖音、百度等)和鸿蒙系统上36。它采用原生渲染,性能接近原生项目,且完全兼容 Vue2/Vue3 语法,零学习成本。

老肖的博客 165

如何用PolyCSS实现3D模型骨骼动画?glTF/GLB动画系统完整教程

PolyCSS 是一个运行在浏览器 DOM 上的 **CSS 3D 引擎**,它把 glTF/GLB 模型解析为多边形网格,再用 CSS `matrix3d(...)` 变换渲染成真实 HTML 元素——这意味着你无需 WebGL 就能实现 **3D 模型骨骼动画**。本文将带你完整走通 PolyCSS 的 glTF/GLB 动画系统:从模型解析、骨骼蒙皮,到 Mixer 播放器和 React/V

gitblog_00766的博客 195

newforms FormSet 完全指南:动态多表单增删与删除标记的终极方案

**newforms FormSet** 是 React 同构表单库 newforms 中的多表单管理方案,让你在同一个页面里轻松实现"动态添加、删除、排序多个表单",并通过 **DELETE 删除标记** 安全地标记待删除数据。无论你是做地址簿、购物车还是批量资料录入,这篇 FormSet 完全指南都能帮你快速上手。 ## 为什么需要 FormSet?🧩 想象这样一个场景:用户要一次性填写

gitblog_00445的博客 98

oRPC × NestJS Playground 实战指南:contract-first 类型安全 API 与 OpenTelemetry 可观测性

本篇以 oRPC 仓库中的 [playgrounds/nest](https://link.gitcode.com/i/1c9f7dcd8c0f1c2f1f96aad44d13de8c) 为例,完整拆解一个将 contract-first 类型安全 API 落地到 NestJS 的可运行示例工程:从契约定义、`@Implement` 装饰器实现、OpenAPI 规范自动生成与 Scalar UI

gitblog_00342的博客 1046

list包含某个字符串_Python超详细的字符串用法大全

本文要点字符串拼接拆分含有多种分隔符的字符串判读字符串a是否以字符串b开头或结尾调整字符串中文本的格式对字符串进行左,右,居中对齐删除字符串中不需要的字符字符串拼接实际场景:把列表中的数据拼接成一个字符串解决方案:使用 str.join() 方法>>>li=['cxk','cxk','kk','caibi']>>>''.join([str...

weixin_39620151的博客 2614
上一篇: React访问input内容,不使用onChange方法
下一篇: 小鸡啄米之React项目构建
天落枫
博客等级 码龄10年 91粉丝 92原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值