如何在 React 中正确地使用 useRef 钩子来访问动态生成的多个子组件的 DOM 节点?

如何在 React 中正确地使用 useRef 钩子来访问动态生成的多个子组件的 DOM 节点?

回答与解析:

在 React 中,若需要访问动态生成的多个子组件(或元素)的 DOM 节点,不能直接将同一个 useRef 对象赋给多个元素,因为 useRef 只能引用一个 DOM 节点。正确做法是使用一个 ref 数组,配合 useCallback 或自定义 ref 回调函数来动态收集每个元素的引用。

示例代码:

import { useRef, useCallback } from 'react';

function App() {
  const itemRefs = useRef([]);

  // 使用 useCallback 确保函数引用稳定
  const setItemRef = useCallback((element, index) => {
    itemRefs.current[index] = element;
  }, []);

  const items = ['A', 'B', 'C'];

  const handleClick = (index) => {
    // 聚焦对应项
    itemRefs.current[index]?.focus?.();
  };

  return (
    <div>
      {items.map((item, index) => (
        <input
          key={index}
          ref={(el) => setItemRef(el, index)}
          defaultValue={item}
        />
      ))}
      <button onClick={() => handleClick(1)}>聚焦第二项</button>
    </div>
  );
}

关键点解析:

  1. 不要直接写 ref={itemRefs[index]}:因为 itemRefs.current 是一个普通数组,不是由 useRef 创建的响应式对象,直接赋值无法在渲染时正确绑定。
  2. 使用回调 ref(callback ref):通过 (el) => setItemRef(el, index),每次元素挂载或卸载时会调用该函数,从而将 DOM 节点存入 ref 数组。
  3. useCallback 优化:避免每次渲染都创建新函数,保持 setItemRef 引用稳定,防止不必要的 ref 重置。
  4. 注意 key 的稳定性:动态列表应使用稳定且唯一的 key,否则 ref 可能错乱。

此方法适用于需要直接操作多个 DOM 元素(如聚焦、测量尺寸、动画等)的场景,是 React 官方推荐的处理多 ref 的方式。

发表评论 (审核通过后显示评论):

昵称:
邮箱:
内容: