You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 10:15:09