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

React中通过cloneElement为子组件设置并访问refs问题

解决React整页滚动组件中Refs未正确绑定的问题

问题根源

你代码里的refs数组是用let直接声明的,函数组件每次渲染都会重新生成这个数组,导致子组件挂载时关联的ref对象和点击按钮时打印的不是同一个实例,所以current始终为undefined。另外,没有用React的useRef来持久化这些引用,导致挂载后引用丢失。

修正后的完整代码

FullPageContainer 组件

import React from "react";

export const FullPageContainer = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  // 用useRef持久化refs数组,确保组件生命周期内引用不变
  const refs = React.useRef<(React.RefObject<HTMLDivElement>)[]>([]);

  // 当子组件数量变化时,同步更新refs数组长度
  React.useEffect(() => {
    const childCount = React.Children.count(children);
    refs.current = Array(childCount).fill(null).map(() => React.createRef<HTMLDivElement>());
  }, [children]);

  const childrenWithProps = React.Children.map(children, (child, index) => {
    if (React.isValidElement(child)) {
      // 给每个子组件绑定对应的持久化ref
      return React.cloneElement(child, { ref: refs.current[index] });
    }
    return child;
  });

  // 实现滚动到指定section的核心函数
  const scrollToSection = (index: number) => {
    const targetSection = refs.current[index];
    if (targetSection?.current) {
      targetSection.current.scrollIntoView({
        behavior: "smooth",
        block: "start"
      });
    }
  };

  return (
    <div>
      <button onClick={() => console.log(refs.current)}>查看Refs状态</button>
      <button onClick={() => scrollToSection(0)}>滚动到第1屏</button>
      <button onClick={() => scrollToSection(1)}>滚动到第2屏</button>
      <button onClick={() => scrollToSection(2)}>滚动到第3屏</button>
      {childrenWithProps}
    </div>
  );
};

FullPageSection 组件

import React from "react";

// 修正forwardRef的类型定义,兼容React的ref传递机制
export const FullPageSection = React.forwardRef<HTMLDivElement, { children: React.ReactNode }>(
  ({ children }, ref) => {
    return (
      <div
        ref={ref}
        style={{
          height: "100vh",
          width: "100%",
          border: "1px solid #eee",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          fontSize: "3rem",
          backgroundColor: "#f5f5f5"
        }}
      >
        {children}
      </div>
    );
  }
);

关键改进点

  • 持久化引用:用useRef存储refs数组,保证组件每次渲染时访问的是同一批ref对象,避免引用丢失。
  • 动态同步:通过useEffect监听子组件数量变化,自动调整refs数组长度,适配子组件增删的场景。
  • 滚动功能实现:新增scrollToSection函数,利用原生scrollIntoView实现平滑滚动,满足整页滚动的核心需求。
  • 类型优化:修正FullPageSection的forwardRef类型,确保ref传递符合React的类型规范,支持对象ref和回调ref。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 17:55:19