React函数组件中useEffect调用无效的问题求助
React函数组件中useHook调用报错:Invalid hook call
问题描述
接触React时间不长,在函数组件中调用useEffect时遇到Invalid hook call报错,排查许久未解决。
Sessions组件代码
import React, { Component } from 'react'; import { useState, useEffect } from "react"; export function Sessions() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [count, setCount] = useState(null); useEffect(() => { fetch(`https://localhost:7126/api/`) .then((response) => { if (!response.ok) { throw new Error( `This is an HTTP error: The status is ${response.status}` ); } return response.json(); }) .then((actualData) => { setData(actualData); setError(null); setCount(actualData.length); }) .catch((err) => { console.log(err.message); }); }, []); return ( <div className="App"> <h1>Stream Request: {count} records</h1> {loading && <div>A moment please...</div>} {error && ( <div>{`There is a problem fetching the post data - ${error}`}</div> )} <ul> {data && data.map(({ StreamId, EntryTime }) => ( <li key={StreamId}> <h3>{EntryTime}</h3> </li> ))} </ul> </div> ); }
报错信息
Warning: 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:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app
已排查内容
- React和React-Dom均为最新版本;
- 通过
npm ls react验证,所有React依赖已去重,输出如下:
+-- react-dom@18.2.0 | `-- react@18.2.0 deduped +-- react-router-dom@6.4.3 | +-- react-router@6.4.3 | | `-- react@18.2.0 deduped | `-- react@18.2.0 deduped +-- react@18.2.0 `-- reactstrap@9.1.5 +-- react-popper@2.3.0 | `-- react@18.2.0 deduped +-- react-transition-group@4.4.5 | `-- react@18.2.0 deduped `-- react@18.2.0 deduped
路由配置代码
App.js
import "./stylesheet.css"; import React, { Component } from 'react'; import { Route, Routes } from 'react-router-dom'; import AppRoutes from './AppRoutes'; import { Layout } from './components/Layout'; export default class App extends Component { static displayName = App.name; render() { return ( <Layout> <Routes> {AppRoutes.map((route, index) => { const { element, ...rest } = route; return <Route key={index} {...rest} element={element} />; })} </Routes> </Layout> ); } }
AppRoutes.js
import { Sessions } from "./components/Sessions"; import { Messages } from "./components/Messages"; import { Home } from "./components/Home"; const AppRoutes = [ { index: true, element: <Home /> }, { path: '/sessions', element: <Sessions /> }, { path: '/messages', element: <Messages /> } ]; export default AppRoutes;
解决方案
1. 修复组件内状态更新逻辑(必做)
你的useEffect未在请求完成(成功/失败)时更新loading状态,也未在错误发生时设置error状态,会导致页面一直显示加载提示且错误无法展示。修改后的useEffect:
useEffect(() => { fetch(`https://localhost:7126/api/`) .then((response) => { if (!response.ok) { throw new Error( `This is an HTTP error: The status is ${response.status}` ); } return response.json(); }) .then((actualData) => { setData(actualData); setError(null); setCount(actualData.length); setLoading(false); // 请求成功后关闭加载状态 }) .catch((err) => { console.log(err.message); setError(err.message); // 设置错误状态 setLoading(false); // 请求失败后关闭加载状态 }); }, []);
2. 排查Hook调用报错核心原因
你已排除版本不兼容和多份React的问题,重点检查以下几点:
- 检查Layout组件:如果
Layout是类组件,确保内部未调用Hook;如果是函数组件,确保所有Hook都在顶层调用,未违反Hook规则。 - 修改组件导出/导入方式:尝试将Sessions改为默认导出:
然后在AppRoutes中修改导入:// Sessions.js export default function Sessions() { // 原有代码不变 }import Sessions from "./components/Sessions"; - 禁用React DevTools:若DevTools版本过旧,可能与React 18不兼容,禁用后刷新页面验证报错是否消失。
- 隔离其他组件干扰:临时注释AppRoutes中的其他路由,仅保留Sessions路由,排查是否为其他组件导致的报错。
3. 优化组件导入语句
合并重复的React导入,简化代码:
import React, { useState, useEffect } from 'react';
内容的提问来源于stack exchange,提问作者MX313
相关产品推荐
相关产品推荐

