React自定义Hook触发Invalid Hook call报错无法定位原因求解
Invalid Hook Call 报错修复方案
优先排查自定义Hook调用位置
你提供的useLogin自定义Hook内部的Hook调用逻辑符合规范,偶现报错大概率是调用该Hook的位置不符合Hook规则,重点检查以下场景:
- 是否在普通JS函数、类组件、条件判断、循环、异步回调内调用
useLogin - 是否在路由跳转、组件销毁后才触发接口返回的状态更新
具体修复方案
1. 修复异步更新导致的内存泄漏报错
你的useEffect中异步请求没有加卸载判断,组件销毁后调用状态更新方法会触发异常,修改代码如下:
export const useLogin = () => { const [signed_in, setSigned_in] = useState(null); const [role, setRole] = useState(null); const [profile, setProfile] = useState(null); useEffect(() => { // 标记组件是否卸载 let isUnmounted = false (async () => { const res = await fetch('/api/profile/', { method: 'GET', headers: { 'Authorization': 'Bearer ' + localStorage.getItem('access_token') } }); // 组件已卸载则不执行后续状态更新 if (isUnmounted) return if (res.ok) { setSigned_in(true); res.json().then(r => { if (isUnmounted) return setRole(r.role); setProfile(r); }).catch(err => alert(err)); } else { setSigned_in(false); setRole(null); } })() // 组件卸载时修改标记位 return () => { isUnmounted = true } }, dependents); return { signed_in, setSigned_in, role, profile, setRole, setProfile }
2. 检查依赖数组合法性
确认useEffect的依赖项dependents是合法定义的数组,不要传递未定义、非数组类型的依赖,也不要遗漏依赖项。
3. 开发环境热更新问题修复
如果是开发环境偶现,生产环境没有复现,大概率是热更新缓存导致,执行以下命令清理缓存即可:
rm -rf node_modules package-lock.json npm install npm start -- --reset-cache
4. 多React副本兜底排查
如果以上方案都无效,可以通过以下代码确认是否存在多副本:
在项目入口文件和useLogin文件分别加入以下代码:
// 入口文件 import React from 'react' window.ReactEntry = React // useLogin文件 import React from 'react' window.ReactHook = React
打开控制台执行console.log(window.ReactEntry === window.ReactHook),如果返回false说明存在多副本,在打包配置中添加React别名即可解决:
// craco.config.js (CRA项目需先安装@craco/craco) const path = require('path') module.exports = { webpack: { alias: { 'react': path.resolve(__dirname, 'node_modules/react'), 'react-dom': path.resolve(__dirname, 'node_modules/react-dom') } } }
内容的提问来源于stack exchange,提问作者Johny
相关产品推荐
相关产品推荐

