如何调用自定义React Hook返回的函数?排查Invalid hook call错误
问题原因
你的代码存在3处核心错误,直接触发了你遇到的两个异常:
- 调用自定义Hook时违反React Hook规则:你定义的Hook名称为
useCheckUnique,调用时错写为CheckUnique,且没有在函数组件顶层作用域调用,直接触发*Invalid hook call. Hooks can only be called inside of the body of a function component.*报错,同时导致返回值异常(出现嵌套函数的对象而非预期的校验函数)。 - Hook入参类型定义错误:
param: keyof typeof self写法完全不成立,self被定义为number | string类型,不存在可提取的属性键,会导致类型校验失效。 - 传参逻辑错误:你定义的校验逻辑里是对比
x.id !== self,但调用时传入的第三个参数是整个item对象而非item.id,会导致唯一性判断逻辑永远不成立。
修正方案
- 严格遵循React Hook调用规则:所有
use开头的自定义Hook,必须在函数组件/自定义Hook的顶层作用域调用,不能放在回调、条件判断、循环里调用,调用时不能省略use前缀。 - 修正Hook的入参类型定义,用泛型约束数组元素类型,保证
param参数是数组元素的合法字段。 - 调用Hook时第三个参数传入当前编辑项的
id,而非整个项对象;用useCallback包裹校验函数,避免每次组件渲染生成新的函数引用,触发不必要的重渲染。
修正后完整代码
自定义Hook定义
import { useCallback } from 'react'; // 按项目实际路径引入useSnack // import { useSnack } from '@/hooks/useSnack'; export const useCheckUnique = <T extends { id?: string | number }>( items: T[], param: keyof T, currentId: string | number, ) => { const { showToast } = useSnack(); const isUnique = useCallback((currentValue: T[keyof T]) => { const isExist = items.some(item => item[param] === currentValue && item.id !== currentId); if (isExist) { showToast({ text: `wizard:${String(param)}_NOT_UNIQUE`, variant: 'danger', }); return false; } return true; }, [items, param, currentId, showToast]); return isUnique; };
组件内调用示例
// 以下代码写在函数组件的顶层作用域,不要写在update等回调函数内 const items = [{id:1, value: 2}, {id:2, value:7}, {id:3, value: 9}]; const currentEditItem = {id:2, value:7}; // 正确调用Hook:注意use前缀,第三个参数传id而非整个对象 const checkValueAvailable = useCheckUnique(items, 'value', currentEditItem.id); // 渲染部分 <EntityFieldsetItem title="example" value={value} update={(newValue) => { if (checkValueAvailable(newValue)) { // 执行正常更新逻辑 } }} />
内容的提问来源于stack exchange,提问作者coolps811
相关产品推荐
相关产品推荐

