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

如何在React中获取嵌套二级组件Baz的聚合Ref列表?

获取所有Baz组件的聚合Ref列表方案

要实现跨多层组件收集所有Baz的Ref,需要通过逐层传递收集逻辑来实现,以下是两种可行方案:

方案一:通过回调Props收集

1. 修正Baz组件,支持接收外部Ref

const Baz = React.forwardRef<HTMLDivElement>((_, ref) => {
  return <div ref={ref}>Test</div>;
});

2. 修改Bar组件,内部收集Baz的Ref并传递给父组件

const Bar = ({ onBazRefsCollected }: { onBazRefsCollected: (refs: Array<HTMLDivElement | null>) => void }) => {
  const bazRefs = React.useRef<Array<HTMLDivElement | null>>([]);

  // 组件挂载/更新后,将内部Baz的Ref数组传递给父组件
  React.useEffect(() => {
    onBazRefsCollected(bazRefs.current);
    // 卸载时清空对应Ref,避免无效引用
    return () => onBazRefsCollected([]);
  }, [onBazRefsCollected]);

  return (
    <div>
      {[0, 1, 2].map((_, index) => (
        <Baz key={index} ref={(el) => (bazRefs.current[index] = el)} />
      ))}
    </div>
  );
};

3. 在Foo组件中聚合所有Baz的Ref

const Foo = () => {
  const allBazRefs = React.useRef<Array<HTMLDivElement | null>>([]);

  // 处理每个Bar传递的Ref数组,更新总列表
  const handleBazRefsCollected = (barIndex: number, refs: Array<HTMLDivElement | null>) => {
    // 定位当前Bar在总列表中的位置,替换旧的Ref
    const startPos = barIndex * 3;
    allBazRefs.current.splice(startPos, refs.length, ...refs);
  };

  return (
    <div>
      {[0, 1, 2, 3].map((i) => (
        <Bar key={i} onBazRefsCollected={(refs) => handleBazRefsCollected(i, refs)} />
      ))}
    </div>
  );
};

方案二:通过ForwardRef让Bar暴露内部Baz的Ref数组

1. 修正Baz组件(同方案一)

const Baz = React.forwardRef<HTMLDivElement>((_, ref) => {
  return <div ref={ref}>Test</div>;
});

2. 修改Bar组件,通过ForwardRef暴露内部Baz的Ref数组

const Bar = React.forwardRef<Array<HTMLDivElement | null>>((_, ref) => {
  const bazRefs = React.useRef<Array<HTMLDivElement | null>>([]);

  // 将内部Baz的Ref数组传递给父组件的Ref
  React.useEffect(() => {
    if (typeof ref === 'function') {
      ref(bazRefs.current);
    } else if (ref) {
      ref.current = bazRefs.current;
    }
  }, [ref]);

  return (
    <div>
      {[0, 1, 2].map((_, index) => (
        <Baz key={index} ref={(el) => (bazRefs.current[index] = el)} />
      ))}
    </div>
  );
});

3. 在Foo组件中聚合所有Baz的Ref

const Foo = () => {
  const barRefs = React.useRef<Array<Array<HTMLDivElement | null>>>([]);
  const allBazRefs = React.useRef<Array<HTMLDivElement | null>>([]);

  // 当Bar的Ref数组更新时,合并为一维数组
  React.useEffect(() => {
    allBazRefs.current = barRefs.current.flat();
  }, [barRefs.current]);

  return (
    <div>
      {[0, 1, 2, 3].map((i) => (
        <Bar key={i} ref={(refs) => (barRefs.current[i] = refs)} />
      ))}
    </div>
  );
};

注意事项

  • 所有列表项必须添加key属性,避免React渲染警告;
  • 组件卸载时需清理对应Ref引用,防止内存泄漏;
  • 若Baz的数量动态变化,需在Bar组件中监听数量变化,调整Ref收集逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:10:33