React+Mobx两台机器一台报“Invalid hook call”问题求助
问题背景
我正在学习Mobx相关内容,代码在一台机器上运行正常,但另一台机器执行npm start时出现Hook调用错误,只要不使用observer包裹函数组件,错误就消失。两台机器仅npm版本不同(报错机器为npm 8.13.2,正常机器为npm 8.11.0),React、mobx-react、mobx-react-lite版本均一致(分别为18.2.0、7.5.2、3.4)。
错误信息如下:
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component.
Uncaught TypeError: Cannot read properties of null (reading 'useState')
at Object.useState (react.development.js:1622:1)
at useObserver (useObserver.ts:29:1)
at observerComponent (observer.ts:104:1)
at renderWithHooks (react-dom.development.js:16305:1)
at updateFunctionComponent (react-dom.development.js:19588:1)
at updateSimpleMemoComponent (react-dom.development.js:19425:1)
at updateMemoComponent (react-dom.development.js:19284:1)
at beginWork (react-dom.development.js:21673:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
核心原因
这个错误的本质是React Hook调用的上下文环境异常,结合npm版本差异和observer触发的条件,主要原因有两点:
- npm版本差异导致多版本React冲突:npm 8.13.x的依赖解析逻辑和8.11.x存在细微差异,可能导致项目中安装了多个不同实例的React。当
mobx-react内部的useObserver调用useState时,它引用的React实例和业务组件使用的React实例不是同一个,违反了React Hook必须在同一实例的函数组件体内调用的规则,从而触发错误。 - 依赖安装的隐性版本不匹配:虽然指定了React和Mobx相关包的版本,但npm 8.13.2可能在安装时拉取了
mobx-react依赖链中未严格锁定的子依赖,导致React相关包的版本出现隐性不兼容,引发Hook调用时上下文为null的问题。
解决方案
1. 清理依赖并重新安装
- 删除项目根目录下的
node_modules文件夹和package-lock.json文件 - 执行
npm cache clean --force清除npm本地缓存 - 重新运行
npm install,确保依赖安装完全一致
2. 强制锁定依赖版本
在package.json中添加resolutions字段(npm 8及以上版本支持),强制统一React和Mobx相关依赖的版本:
"resolutions": { "react": "18.2.0", "react-dom": "18.2.0", "mobx-react": "7.5.2", "mobx-react-lite": "3.4.0" }
添加完成后执行npm install让配置生效。
3. 检查并解决重复React实例
运行npm ls react查看项目中所有React实例的版本和来源,如果输出中出现多个版本的React,说明存在依赖冲突,需要通过resolutions字段强制统一版本。
4. 降级npm版本
如果上述方法无效,可以将报错机器的npm版本降级到8.11.0:
npm install -g npm@8.11.0
降级完成后重新清理依赖并安装运行。
内容的提问来源于stack exchange,提问作者matohak

