You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React循环渲染元素时创建Ref遇异常,如何修复?

React 数组元素 Ref 创建异常问题

我有一个React元素数组,通过map函数进行渲染:

{ elemsList.map((item, i) => { 
    return (
        <div 
           key={i}
           ref={refsArr[i]}
           data-grid={item.props["data-grid"]}
           onClick={e => doubleClickHandler(item.key, e)}
           style={{ 
                backgroundColor: i === selectedComponent ? '#828EE3' : "#102f6a", 
                color: "#fff", 
                height: "100%",
           }}
        >
            {item}
        </div>
    )}
) }

尝试通过useRef创建数组来为每个元素绑定Ref:

const refsArr = useRef([])
refsArr.current = elemsList.map((item, i) => refsArr.current[i] ?? setTimeout(createRef(), 5000))
...
{ elemsList.map((item, i) => { 
    return (
        <div 
           key={i}
           ref={refsArr[i]}
           data-grid={item.props["data-grid"]}
           onClick={e => doubleClickHandler(item.key, e)}
           style={{ 
                backgroundColor: i === selectedComponent ? '#828EE3' : "#102f6a", 
                color: "#fff", 
                height: "100%",
           }}
        >
            {item}
        </div>
    )}
) }

当前问题:控制台输出Ref数组时,得到的不是正常的Ref对象,而是类似{ current: [53] }的结果,该如何修复?


错误原因分析

  1. setTimeout误用:setTimeout(createRef(), 5000)会立即执行createRef(),并将setTimeout返回的定时器ID(即数字53这类值)赋值给数组项,完全偏离了创建Ref的逻辑。
  2. Ref数组访问错误:refsArr是useRef返回的对象,真正的数组存储在refsArr.current中,渲染时误用了refsArr[i]而非refsArr.current[i]。
  3. 初始化逻辑混乱:直接覆盖refsArr.current的方式会干扰React的Ref绑定机制,导致Ref对象无法正确关联DOM节点。

正确实现方式

方式1:按需初始化Ref数组

import { useRef, useEffect } from 'react';

// ...

const refsArr = useRef([]);

// 确保Ref数组长度与elemsList匹配,按需创建Ref
useEffect(() => {
  refsArr.current = elemsList.map((_, i) => refsArr.current[i] ?? createRef());
}, [elemsList]);

// 渲染部分
{elemsList.map((item, i) => (
  <div 
    key={i}
    ref={refsArr.current[i]} // 正确访问current中的数组项
    data-grid={item.props["data-grid"]}
    onClick={e => doubleClickHandler(item.key, e)}
    style={{ 
      backgroundColor: i === selectedComponent ? '#828EE3' : "#102f6a", 
      color: "#fff", 
      height: "100%",
    }}
  >
    {item}
  </div>
))}

方式2:使用回调Ref(更灵活)

无需维护Ref数组的初始化逻辑,直接通过回调将DOM节点存入数组:

const refsArr = useRef([]);

// 回调Ref函数,将DOM节点存入数组对应位置
const setRef = (el, index) => {
  refsArr.current[index] = el;
};

// 渲染部分
{elemsList.map((item, i) => (
  <div 
    key={i}
    ref={el => setRef(el, i)}
    data-grid={item.props["data-grid"]}
    onClick={e => doubleClickHandler(item.key, e)}
    style={{ 
      backgroundColor: i === selectedComponent ? '#828EE3' : "#102f6a", 
      color: "#fff", 
      height: "100%",
    }}
  >
    {item}
  </div>
))}

验证方法

修复后,通过console.log(refsArr.current)即可查看正确的Ref数组,每个数组项都是包含current属性的Ref对象,指向对应的DOM节点。

内容的提问来源于stack exchange,提问作者Listopad02

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:27:32