React+TypeScript中useEffect报错number不可赋值给void|Destructor如何解决
报错原因
- 第一个报错
Type number is not assignable to type 'void | Destructor':你给useEffect传的回调用了不带花括号的单行箭头函数写法,此时boundsArray.push(xxx)的返回值(数组的新长度,number类型)会被作为useEffect回调的返回值。但useEffect规定回调只能返回销毁函数(Destructor)或者无返回值(void),不符合类型要求所以报错。 - 第二个初始报错和修改后残留的类型报错:
- 最初的
Array<number>[]是二维数字数组的类型声明,和你要存储单个数字的预期不符,修改为Array<number>后仅解决了维度不匹配的问题 - 你只声明了
boundsArray变量没有初始化,实际值为undefined,调用push方法本身就会触发运行时错误 props.elementBounds.current?.getBoundingClientRect().top用了可选链,当ref还没绑定到DOM元素时,current为null,整个表达式返回undefined,无法赋值给要求元素为number类型的数组,所以触发类型不兼容报错。
- 最初的
修复方案
- 给useEffect回调加上花括号,避免把push的返回值作为回调返回值
- 初始化
boundsArray变量,如果需要跨渲染周期保留数组内容,建议用useRef存储(普通let变量每次组件渲染都会重置) - 加判断逻辑,确保ref绑定到DOM元素后再读取top值,避免出现undefined
修复后的DraggableGameAnswers组件代码:
import { RefObject, useEffect, useRef } from 'react'; type DraggableGameAnswersProps = { elementBounds: RefObject<HTMLDivElement> } function DraggableGameAnswers(props: DraggableGameAnswersProps) { // 用useRef存储数组,跨渲染周期保留内容 const boundsArrayRef = useRef<Array<number>>([]); useEffect(() => { // 先判断current是否存在,避免读取到undefined if (props.elementBounds.current) { const top = props.elementBounds.current.getBoundingClientRect().top; boundsArrayRef.current.push(top); } // 可根据业务需要补充依赖数组,避免useEffect重复执行 }, [props.elementBounds]) return ( <div className="draggable-game-answers"> test </div> ); } export default DraggableGameAnswers;
如果你不需要跨渲染保留数组内容,仅单次useEffect内使用,可以直接在useEffect内部声明数组,不需要在组件顶层定义。
内容的提问来源于stack exchange,提问作者Octavian Niculescu
相关产品推荐
相关产品推荐

