登录
首页 >  文章 >  前端

ReactuseRef动态数组引用技巧

时间:2026-02-10 08:03:40 268浏览 收藏

一分耕耘,一分收获!既然打开了这篇文章《React useRef 创建动态数组引用方法》,就坚持看下去吧!文中内容包含等等知识点...希望你能在阅读本文后,能真真实实学到知识或者帮你解决心中的疑惑,也欢迎大佬或者新人朋友们多留言评论,多给建议!谢谢!

如何在 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<(HTMLDivElement | null)[]>([]);

  // 确保 refs.current 长度匹配(避免 stale length)
  useEffect(() => {
    if (refs.current.length < length) {
      refs.current = Array(length).fill(null);
    }
  }, [length]);

  return refs;
};

const MyComponent = () => {
  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>
        );
      })}

      {/* 导航按钮示例 */}
      <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 开销)。

终于介绍完啦!小伙伴们,这篇关于《ReactuseRef动态数组引用技巧》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布文章相关知识,快来关注吧!

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>