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

React中useState Hook无效调用错误的解决方案咨询

React useState Hook触发Invalid hook call错误的排查与解决

错误信息

react-dom.development.js:16227 
        
       Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
    at Object.throwInvalidHookError (react-dom.development.js:16227:1)
    at useState (react.development.js:1622:1)
    at MenuWrapper (menuWrapper.jsx:16:1)
    at MenuList.jsx:12:1
    at Array.map (<anonymous>)
    at MenuList (MenuList.jsx:8:1)
    at Menu.render (menu.jsx:108:1)
    at finishClassComponent (react-dom.development.js:19752:1)
    at updateClassComponent (react-dom.development.js:19698:1)
    at beginWork (react-dom.development.js:21611:1)
react-dom.development.js:18687 
        
       The above error occurred in the <Menu> component:

    at Menu (http://localhost:3000/static/js/bundle.js:385:5)
    at div
    at div
    at App (http://localhost:3000/static/js/bundle.js:62087:78)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
logCapturedError @ react-dom.development.js:18687
react-dom.development.js:26923 
        
       Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
    at Object.throwInvalidHookError (react-dom.development.js:16227:1)
    at useState (react.development.js:1622:1)
    at MenuWrapper (menuWrapper.jsx:16:1)
    at MenuList.jsx:12:1
    at Array.map (<anonymous>)
    at MenuList (MenuList.jsx:8:1)
    at Menu.render (menu.jsx:108:1)
    at finishClassComponent (react-dom.development.js:19752:1)
    at updateClassComponent (react-dom.development.js:19698:1)
    at beginWork (react-dom.development.js:21611:1)

package.json配置

{
  "name": "jonathan",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "dependencies": {
    "@babel/runtime": "^7.5.0",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^14.4.3",
    "airbnb-prop-types": "^2.16.0",
    "axios": "^1.1.3",
    "bootstrap": "^5.2.2",
    "create-webpack-config": "^0.2.1",
    "html-webpack-plugin": "^5.5.0",
    "jquery": "^3.6.1",
    "mdb-react-ui-kit": "^4.2.0",
    "react": "^18.2.0",
    "react-bootstrap": "^2.5.0",
    "react-bootstrap-accordion": "^1.0.0",
    "react-dom": "^18.2.0",
    "react-helmet": "^6.1.0",
    "react-onclickout": "^2.0.8",
    "react-outside-click-handler": "^1.3.0",
    "react-router": "^6.4.2",
    "react-router-dom": "^6.4.2",
    "react-script-tag": "^1.1.2",
    "react-scripts": "^5.0.1",
    "type-fest": "^3.1.0",
    "webpack-dev-server": "^4.11.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "description": "This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).",
  "main": "index.js",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.19.6",
    "@babel/node": "^7.20.0",
    "@babel/preset-env": "^7.19.4",
    "@babel/preset-react": "^7.18.6",
    "web-vitals": "^3.0.4",
    "webpack": "^5.74.0",
    "webpack-cli": "^4.10.0"
  }
}

相关组件代码

import React, { useState }from "react";
    
import Area from "../ReadFolder/geographicMainComponents/areaMainComponent.jsx";
import City from "../ReadFolder/geographicMainComponents/cityMainComponent.jsx";
import Country from "../ReadFolder/geographicMainComponents/countryMainComponent.jsx";
import Neighborhood from "../ReadFolder/geographicMainComponents/neighborhoodMainComponent.jsx";
import Region from "../ReadFolder/geographicMainComponents/regionMainComponent.jsx";
import { default as AreaW} from "../WriteFolder/geographicMainComponents/areaMainComponent.jsx";
import { default as CityW} from "../WriteFolder/geographicMainComponents/cityMainComponent.jsx";
import { default as CountryW} from "../WriteFolder/geographicMainComponents/countryMainComponent.jsx";
import { default as  NeighborhoodW} from "../WriteFolder/geographicMainComponents/neighborhoodMainComponent.jsx";
import { default as  RegionW} from "../WriteFolder/geographicMainComponents/regionMainComponent.jsx";
    
export function MenuWrapper(type,id,isEdit){
  let [edit,setEdit] = useState(isEdit);
  if(isEdit){
     if(type==='country'){
          return(  
                   <div>
                      <div className={edit ? 'd-block' :'d-none'}><CountryW id={id}/><button onclick={() => setEdit=false}>read</button></div>
                      <div className={edit ? 'd-none' : 'd-block'}><Country id={id} /><button onclick={() => setEdit=true}>edit</button></div>
                   </div>
                   );
     }
     else{return(<div></div>)}
  }
  else{return(<div></div>)}
}
import React,{Component} from "react";
import { MenuWrapper } from "./menuWrapper.jsx";
export function MenuList(Items,kind){
    if(Items===null){
        return(<div></div>)
    }
    return(
        <div>
           
                {
                   Items.map((item)=>{
                        return(
                            MenuWrapper(kind,item.id,false)
                        )
                    })
                }
            
        </div>    );
}

已尝试操作

  • 删除package-lock.json和node_modules,执行npm install --force后重启项目,问题未解决。

排查与解决建议

核心问题分析

错误提示明确指向违反了Hook规则:Hooks只能在函数组件的顶层或自定义Hook中调用。你的代码存在两个关键问题:

  1. MenuWrapper不是标准的React函数组件:它直接接收独立参数而非React组件要求的props对象,且你在MenuList中像调用普通函数一样执行MenuWrapper(kind,item.id,false),而非以JSX组件形式<MenuWrapper />渲染,导致useState在非React组件上下文执行。
  2. MenuList同样不符合React组件规范,接收参数方式错误,且未以正确方式渲染子组件。

修复步骤

1. 修复MenuWrapper组件

将其改为标准的React函数组件,接收props对象,同时修正事件绑定和状态更新的错误:

import React, { useState }from "react";

// 导入组件部分保持不变
import Area from "../ReadFolder/geographicMainComponents/areaMainComponent.jsx";
import City from "../ReadFolder/geographicMainComponents/cityMainComponent.jsx";
import Country from "../ReadFolder/geographicMainComponents/countryMainComponent.jsx";
import Neighborhood from "../ReadFolder/geographicMainComponents/neighborhoodMainComponent.jsx";
import Region from "../ReadFolder/geographicMainComponents/regionMainComponent.jsx";
import { default as AreaW} from "../WriteFolder/geographicMainComponents/areaMainComponent.jsx";
import { default as CityW} from "../WriteFolder/geographicMainComponents/cityMainComponent.jsx";
import { default as CountryW} from "../WriteFolder/geographicMainComponents/countryMainComponent.jsx";
import { default as  NeighborhoodW} from "../WriteFolder/geographicMainComponents/neighborhoodMainComponent.jsx";
import { default as  RegionW} from "../WriteFolder/geographicMainComponents/regionMainComponent.jsx";

// 接收props对象,解构出需要的参数
export function MenuWrapper({ type, id, isEdit }) {
  const [edit, setEdit] = useState(isEdit);
  
  // React事件名需用驼峰式onClick,且setEdit是函数需调用而非赋值
  if (isEdit) {
    if (type === 'country') {
      return (  
        <div>
          <div className={edit ? 'd-block' :'d-none'}>
            <CountryW id={id}/>
            <button onClick={() => setEdit(false)}>read</button>
          </div>
          <div className={edit ? 'd-none' : 'd-block'}>
            <Country id={id} />
            <button onClick={() => setEdit(true)}>edit</button>
          </div>
        </div>
      );
    }
    return <div></div>;
  }
  return <div></div>;
}

2. 修复MenuList组件

改为标准函数组件,接收props,并以JSX形式渲染MenuWrapper,同时添加列表项必需的key属性:

import React from "react";
import { MenuWrapper } from "./menuWrapper.jsx";

// 接收props对象,解构参数
export function MenuList({ items, kind }) {
  if (!items) {
    return <div></div>;
  }
  return (
    <div>
      {items.map((item) => (
        // 列表项必须添加唯一key属性
        <MenuWrapper key={item.id} type={kind} id={item.id} isEdit={false} />
      ))}
    </div>
  );
}

3. 排除其他潜在问题

  • 版本匹配:你的react和react-dom均为18.2.0,版本一致,排除版本不匹配问题。
  • 多React副本:若修复后仍有问题,执行npm ls react查看是否存在多个React版本,若有则执行npm dedupe合并依赖。

内容的提问来源于stack exchange,提问作者jonathan Daboush

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 04:15:42