React自定义Hook导出函数构建报错与TS类型错误咨询
问题解答
1. 保留对象形式导出Hook的可行方案
自定义Hook返回对象是React生态完全通用、合规的写法,绝大多数开源自定义Hook都采用这种形式,你的生产构建报错和返回对象的写法本身没有任何关系,完全不需要修改返回格式。
触发Objects are not valid as a React child报错的核心原因是:useMyHook()返回的对象被直接当做React节点插入到了JSX中渲染,常见的错误场景包括:
- 在JSX模板中直接写了
{useMyHook()},没有提前解构取值 - 调用Hook时漏写解构,把整个返回值对象存到变量后,不小心把变量放到了JSX的渲染位置
- 错误把
useMyHook当做组件写在JSX里(比如写成<useMyHook />)
排查修复步骤:
- 全局搜索所有调用
useMyHook的位置,确认所有调用都符合Hook规则:只在React函数组件/其他自定义Hook的顶层作用域调用,不在条件判断、循环、普通回调函数里调用 - 检查组件return的JSX内容,逐行确认没有把Hook返回的整个对象放到大括号里渲染
- 确认没有把Hook名首字母小写的特性搞错,误将Hook当做组件在JSX中以标签形式使用
修复上述误渲染问题后,对象形式的导出可以正常通过生产构建,且代码可读性最高,是优先推荐的实现方式。
2. 数组形式导出的TypeScript类型错误修复
如果选择数组形式返回Hook内容,出现类型报错的原因是:TypeScript默认会将[func1, func2, func3]推断为元素类型为函数联合类型的普通数组,无法识别数组每个位置对应的具体函数类型,解构后会将所有函数的参数要求做合并,才会错误提示func1需要传入type参数。
修复方式非常简单,在Hook返回数组时添加as const类型断言,将数组标记为只读元组,TypeScript即可精准匹配每个位置的函数类型,修改后的Hook代码如下:
const useMyHook = () => { const func1 = (): boolean => { /* 业务逻辑 */ } const func2 = (type: "type1" | "type2"): boolean => { /* 业务逻辑 */ } const func3 = (): boolean => { /* 业务逻辑 */ } // 添加as const断言固定元组类型 return [func1, func2, func3] as const } export default useMyHook
添加断言后,再通过数组解构获取func1时,TypeScript可以正确识别其不需要传入参数的类型定义,不会再报参数缺失错误。
注意:数组形式返回存在隐式依赖顺序的问题,如果后续调整Hook内返回函数的顺序,所有解构使用该Hook的位置都会出现取值错误,可维护性比对象形式差,非必要不推荐使用。
内容的提问来源于stack exchange,提问作者Andy Hoffman
相关产品推荐
相关产品推荐

