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
相关产品推荐
相关产品推荐

