React使用useRef监听标题鼠标移动时,触发clientWidth读取undefined报错的问题求解
报错根因
触发这个报错的原因有两个:
- 对useRef的返回值结构理解错误:
useRef()返回的对象仅会通过current属性存储绑定的DOM/组件实例,你代码中尝试读取的refs.heading属性从未被定义,值天然为undefined,访问它的clientWidth就会直接抛出报错。 - 原代码存在语法漏写:
function Main的函数体没有用花括号包裹,会直接导致编译不通过。
修复方案
单DOM绑定的最简改法
你当前的代码只需要给一个h1元素绑定ref,完全没必要做多ref集合的结构,直接调整取值逻辑即可:
- 给useRef传入
null作为初始值,规避首次渲染时的空引用问题 - 绑定ref后,通过
refs.current读取对应的DOM节点
修复后的可运行代码:
import React, { useState, useRef } from 'react'; function Main() { const headingRef = useRef(null) const onMouseMove = () => { // 增加空值判断,避免ref未挂载时的边缘报错 if (!headingRef.current) return const width = headingRef.current.clientWidth const height = headingRef.current.clientHeight console.log(width, height); } return ( <div className='home__main-text-wrapper' > <h1 className='heading' onMouseMove={onMouseMove} ref={headingRef} > Get your pet <br /> a perfect ID photo </h1> </div> ) }
这里把原来命名模糊的refs改成语义明确的headingRef,避免后续维护时混淆ref用途。
多DOM绑定的对应写法
如果你后续需要在组件中绑定多个DOM节点,确实要用到多ref存储的场景,正确的写法如下:
import React, { useState, useRef } from 'react'; function Main() { // 在current中提前声明所有需要的ref key const refs = useRef({ heading: null, }) const onMouseMove = () => { if (!refs.current.heading) return const width = refs.current.heading.clientWidth const height = refs.current.heading.clientHeight console.log(width, height); } return ( <div className='home__main-text-wrapper' > <h1 className='heading' onMouseMove={onMouseMove} // 用回调ref把DOM实例赋值到current对应key上 ref={(el) => (refs.current.heading = el)} > Get your pet <br /> a perfect ID photo </h1> </div> ) }
注意:这种场景下不能直接把整个refs对象传给h1的ref属性,否则DOM实例会直接被赋值到refs.current上,而不是refs.heading,会和你代码里的取值逻辑不匹配。
内容的提问来源于stack exchange,提问作者Emily Scone
相关产品推荐
相关产品推荐

