使用useContext从函数组件更新类组件状态时触发无效钩子调用错误
问题分析与修复方案
你遇到的invalid hook call错误,核心原因是违反了React钩子的使用规则:钩子只能在函数组件的顶层作用域调用,不能嵌套在其他函数(比如点击事件回调)里。
看你的Home组件代码,ContextMenuId是一个嵌套函数,你在里面调用了useContext(AppContext),这直接触发了钩子调用错误。
修复步骤
- 将
useContext移到组件顶层:提前在Home组件的最外层获取上下文对象,不要等到点击事件触发时才调用钩子。 - 不要直接修改上下文属性:上下文里的
route来自App组件的state,不能直接赋值修改,应该通过App提供的updateMenuId方法让父组件自己更新state。 - 修正App组件的路由更新逻辑:原
updateMenu方法里把route设为字符串'menu',但原有state里route是parseRoute返回的对象(含path属性),需保持格式一致,避免后续路由判断出错。
修正后的关键代码
Home组件(核心修改部分)
export default function Home() { // 把useContext移到组件顶层,符合钩子使用规则 const context = useContext(AppContext); const [locations, setLocations] = useState({ locations: ['no results'] }); const searchInput = useRef(null); // ... 其余原有代码保持不变 ... // 重构点击处理函数,直接使用顶层获取的上下文 const handleMenuClick = (id) => { // 调用App提供的方法更新状态,不直接修改上下文属性 context.updateMenuId(id); console.log('Id', id); }; // ... 其余原有代码保持不变 ... // 在渲染按钮时,调用重构后的处理函数 // 示例(LocSetup函数内的按钮): <button onClick={() => handleMenuClick(location.brand_id)}> Link to items on menu under 500 calories </button> }
App组件(修正路由更新逻辑)
updateMenu(id) { // 保持route为parseRoute返回的对象格式,和初始化逻辑一致 this.setState({ route: parseRoute('#menu'), menuId: id }); }
内容的提问来源于stack exchange,提问作者Giancarlo Massoni
相关产品推荐
相关产品推荐

