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

React+TypeScript使用ref数组时报classList、getBoundingClientRect不存在错误

解决方案

错误根因

报错的核心原因是操作对象类型不匹配:

  • React.RefObject类型仅包含current属性存储绑定的DOM实例,本身不存在classList、getBoundingClientRect等DOM原生方法
  • 你使用回调ref给数组项赋值时直接传入DOM元素,和初始定义的React.RefObject<HTMLElement>[]类型不匹配,进一步引发类型错误

推荐修改方案(直接存储DOM实例数组)

1. 修改ref定义

去掉多余的React.RefObject嵌套,直接声明为DOM元素数组,不需要提前生成createRef实例:

const categoriesContentRef = useRef<(HTMLElement | null)[]>(
  Array(data.categories.length).fill(null)
);

2. 修改点击事件逻辑

先判空再调用DOM方法,同时替换掉any类型的事件参数:

const clickHandler = (event: React.MouseEvent<HTMLLIElement>) => {
  const id = event.currentTarget.id;
  const category = categoriesContentRef.current.find((item) => {
    return item !== null && item.classList.contains(id);
  });
  if (category) {
    const categoryTop = category.getBoundingClientRect().top;
    const scrollTo = window.scrollY + categoryTop - offset;
    window.scrollTo({
      top: scrollTo,
      behavior: 'smooth',
    });
  }
};

3. 修正forwardRef类型定义

移除ref的any类型声明,使用官方泛型规范类型:

const Categories = React.forwardRef<(HTMLElement | null)[], categoriesProps>(
  ({ allCategories, clickHandler }, ref): JSX.Element => {
    return (
      <CategoriesUlWrapper>
        {allCategories.categories.map((category, index) => {
          return (
            <CategoryLi
              ref={(elm) => {
                if (ref && "current" in ref) {
                  ref.current[index] = elm;
                }
              }}
              key={category.id}
              className={category.name}
              id={category.name}
              onClick={clickHandler}
            >
              <CategoryIcon>
                <ResponsiveImage src={category.img} alt={category.name} />
              </CategoryIcon>
              <CategoryName className="p-20-semi-bold">
                {category.name}
              </CategoryName>
            </CategoryLi>
          );
        })}
      </CategoriesUlWrapper>
    );
  }
);

可选方案(保留RefObject数组写法)

如果需要保留RefObject数组的初始定义,只需要在调用方法前先取每一项的current属性即可:

const category = categoriesContentRef.current.find((item) => {
  return item.current !== null && item.current.classList.contains(id);
});
if (category?.current) {
  const categoryTop = category.current.getBoundingClientRect().top;
  // 其余滚动逻辑不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:18:02