创建React MUI组件库时如何修复"Invalid hook call"错误?
问题背景
用TypeScript构建了一个导出React组件的公共仓库,已配置Storybook和TS,在Storybook中开发组件一切正常,但导入编译后的包使用组件时,出现了"Invalid hook call"错误。组件本身未直接使用React Hook,仅用@mui/lab的TextField做测试组件(Scheduler组件依赖它)。仅使用Button组件时正常,使用Scheduler组件就触发错误。已在peerDependencies中指定与客户端项目相同版本的React及相关依赖,客户端也使用对应版本。
复现步骤
- 克隆仓库后执行
yarn build编译至lib文件夹 - 在空React项目中本地引入该库:
yarn add react-mui-components@file:/yourpath/react-mui-components
- 在客户端项目中使用组件:
import React from 'react'; import { Button, Scheduler } from 'react-mui-components'; const ClientTest: React.FC = () => { return ( <> <Button label={'kristi'} primary={false} /> <Scheduler /> </> ); }; export default ClientTest;
核心原因
这个错误本质是React被重复加载了。虽然在peerDependencies中声明了依赖,但组件库打包时可能把React、ReactDOM或MUI相关依赖打包进了编译产物,导致客户端项目中同时存在两个React实例。Hook的运行依赖单一React实例,因此触发了"Invalid hook call"。Button组件未使用Hook(或其依赖未触发Hook),所以没有报错,而Scheduler依赖的TextField内部使用了Hook,因此暴露了问题。
解决步骤
1. 配置打包工具,外部化peer依赖
确保你的打包工具(Rollup/Webpack)将React、ReactDOM及MUI相关依赖标记为外部依赖,不打包进组件库的产物中。
Rollup配置示例
在rollup.config.js中添加external配置:
export default { // ...其他配置 external: [ 'react', 'react-dom', '@mui/material', '@mui/lab', '@emotion/react', '@emotion/styled' ], // ...其他配置 };
Webpack配置示例
在webpack.config.js中添加externals配置:
module.exports = { // ...其他配置 externals: { react: 'react', 'react-dom': 'react-dom', '@mui/material': '@mui/material', '@mui/lab': '@mui/lab' }, // ...其他配置 };
2. 确认package.json依赖配置
确保peerDependencies正确声明,同时在devDependencies中安装这些依赖(供开发和Storybook使用):
{ "peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "@mui/material": "^5.14.0", "@mui/lab": "^5.0.0-alpha.137" }, "devDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "@mui/material": "^5.14.0", "@mui/lab": "^5.0.0-alpha.137" } }
3. 解决本地测试的重复依赖问题
本地使用file:链接组件库时,可能出现客户端和组件库加载不同React实例的情况,可通过以下方式解决:
方法1:用yarn link共享React实例
# 在组件库目录执行 yarn link # 在客户端项目目录执行 yarn link react-mui-components # 将客户端的React链接到组件库,避免重复 cd ./node_modules/react yarn link cd ../../react-mui-components yarn link react
方法2:用resolutions强制统一版本
在客户端项目的package.json中添加resolutions,强制所有依赖使用同一版本的React:
"resolutions": { "react": "^18.2.0", "react-dom": "^18.2.0" }
然后重新执行yarn install。
4. 检查TS配置
确保tsconfig.json的编译选项正确,特别是jsx、module和outDir:
{ "compilerOptions": { "target": "ESNext", "module": "ESNext", "lib": ["DOM", "DOM.Iterable", "ESNext"], "jsx": "react-jsx", "declaration": true, "declarationDir": "./lib", "outDir": "./lib", "strict": true, "moduleResolution": "NodeNext", "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": false }, "include": ["src"], "exclude": ["node_modules", "lib", "storybook-static"] }
内容的提问来源于stack exchange,提问作者Kristi Jorgji

