如何在 React 中正确使用 useRef 创建动态引用数组

浅磊同学_5974

浅磊同学_5974

2026-01-16

151人浏览

原创

如何在 React 中正确使用 useRef 创建动态引用数组

本文讲解如何规避“react hook 'useref' cannot be called inside a callback”错误,通过 `useref` 持有引用数组并结合回调 ref 实现动态 dom 元素引用管理,适用于滚动定位、焦点控制等场景。

在 React 中,Hooks 的调用必须严格遵守规则:只能在函数组件的顶层或自定义 Hook 的顶层调用,不能在循环、条件语句或回调函数中调用(如 forEach、map 内部)。你原代码中在 labels.forEach(...) 回调里调用 useRef(null),直接违反了这一规则,因此触发 ESLint 和运行时警告。

✅ 正确做法是:用一个 useRef 容器(如数组)统一管理多个 DOM 引用,并通过回调 ref(callback ref)动态赋值。这种方式既符合 Hooks 规则,又能灵活支持动态数量的元素。

✅ 推荐实现方案(推荐用于滚动定位等场景)

import { useRef, useEffect } from 'react';

// 自定义 Hook:返回一个 refs 数组容器和初始化函数
const useDivRefs = (length: number) => {
  const refs = useRef([]);

  // 确保 refs.current 长度匹配(避免 stale length)
  useEffect(() => {
    if (refs.current.length  {
  const labels = ['div 1', 'div 2', 'div 3'];

  // 创建一个 ref 容器,持有 3 个 null 初始值
  const divRefs = useDivRefs(labels.length);

  // 示例:滚动到指定索引的元素
  const scrollToSection = (index: number) => {
    const el = divRefs.current[index];
    if (el) el.scrollIntoView({ behavior: 'smooth' });
  };

  return (
    <div>
      {/* 渲染带 ref 的元素 */}
      {labels.map((label, i) => {
        const targetId = label.replace(/\s+/g, '');
        return (
          <div key="{targetId}" id="{targetId}" ref="{(el)"> {
              divRefs.current[i] = el; // ✅ 安全:不调用 Hook,仅赋值
            }}
            style={{ scrollMarginTop: '80px' }} // 可选:避免被固定头部遮挡
          >
            <h2>{label}</h2>
            <p>Section content...</p><div class="aritcle_card flexRow artxards">
											<div class="artcardd flexRow">
												<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill10835" title="React 组件生成器"><img
														src="https://img.php.cn/upload/skill/001/246/273/6adaf20dee630206.jpg" alt="React 组件生成器" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
												<div class="aritcle_card_info flexColumn">
													<a rel="nofollow" href="/xiazai/skill10835" title="React 组件生成器" class="overflowclass">React 组件生成器</a>
													<p class="overflowclass">根据项目规范生成 React 和 Vue 组件,包括 TypeScript 类型定义、Ant Design 5 集成、Tailwind CSS 样式及 Vitest 测试文件。当用户提出创建、生成或搭建前端组件的需求时启用,例如:“帮我写一个表格组件”、“生成一个弹窗”、“create a form component”、“写一个列表页”、“生成一个下拉选择器”。该能力在以下任一场景触发:涉及 React/TSX/Vue 组件生成、UI 组件创建,或为组件生成测试文件。</p>
												</div>
												<a rel="nofollow" href="/xiazai/skill10835" title="React 组件生成器" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
												</a>
											</div>
										</div>
          </div>
        );
      })}

      {/* 导航按钮示例 */}
      <nav>
        {labels.map((label, i) => (
          <button key="{`btn-${i}`}" onclick="{()"> scrollToSection(i)}
          >
            Go to {label}
          </button>
        ))}
      </nav>
</div>
  );
};

export default MyComponent;

⚠️ 注意事项

  • 不要在 map/forEach 中调用 useRef:每个 useRef() 调用都必须是顶层静态调用,React 依赖调用顺序来匹配 state/ref。
  • 回调 ref 是安全的副作用操作:ref={(el) => {...}} 是纯赋值逻辑,不涉及 Hook 调用,完全合规。
  • useRef([]) 返回的是 MutableRefObject,其 .current 属性可被任意修改,适合存储 DOM 节点列表。
  • 若需响应 labels 动态变化(如增删),建议配合 useEffect 清理或重置 refs.current,避免引用残留。

✅ 总结

要为动态生成的元素创建多个引用,核心思路是:

  1. 单次顶层 useRef 创建容器(如 useRef([]));
  2. 用回调 ref 将节点逐个写入该容器;
  3. 通过索引安全访问(如 refs.current[i])完成滚动、聚焦等交互。

这样既彻底规避了 Rules of Hooks 报错,又保持了代码的可维护性与性能(无重复渲染、无额外 Hook 开销)。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

react html 回调函数

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1698

6

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

2025.12.04

798

13

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

2025.09.05

670

5

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

2025.11.16

343

7

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.17

533

20

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

2025.11.27

303

6

DOM是什么意思
DOM是什么意思

dom的英文全称是documentobjectmodel,表示文件对象模型,是w3c组织推荐的处理可扩展置标语言的标准编程接口;dom是html文档的内存中对象表示,它提供了使用javascript与网页交互的方式。想了解更多的相关内容,可以阅读本专题下面的文章。

2024.08.14

6541

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 12.4万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.4万人学习