自定义React组件库含Hook组件引入触发Invalid Hook Call错误求助
我之前开发内部UI组件库时也碰到过几乎一模一样的问题,结合你提供的配置来看,核心问题应该是组件库打包时没有正确将React等peer依赖排除在外,导致最终打包产物中包含了React实例,和CRA项目中的React形成了多实例冲突——哪怕版本完全一致,只要模块的加载路径不同,React就会认为是两个不同的环境,从而触发Hook调用错误。
下面是具体的解决步骤:
1. 修改Webpack配置,添加externals排除peer依赖
你的webpack.config.js目前没有配置externals,这会导致Webpack把React、React-DOM等peer依赖一起打包进组件库的dist文件里。我们需要告诉Webpack这些依赖应该由使用组件库的项目提供,而不是打包到库本身。
修改后的webpack.config.js:
const path = require('path'); const pkg = require('./package.json'); // 引入package.json module.exports = { mode: 'production', entry: './src/index.js', output: { path: path.resolve('dist'), filename: 'index.js', libraryTarget: 'commonjs2', }, externals: Object.keys(pkg.peerDependencies), // 自动排除所有peer依赖 module: { rules: [ { test: /\.jsx?$/, exclude: /(node_modules)/, use: 'babel-loader', }, { test: /\.(eot|svg|ttf|woff|woff2|otf)$/, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', limit: 10000, mimetype: 'application/font-woff', }, }, ], }, ], }, resolve: { alias: { components: path.resolve(__dirname, 'src/components/'), utils: path.resolve(__dirname, 'src/utils/'), themes: path.resolve(__dirname, 'src/themes/'), }, extensions: ['.js', '.jsx'], }, devtool: false, };
这样配置后,Webpack会自动把你package.json中peerDependencies里的所有依赖都排除在打包范围外,确保组件库使用的是宿主项目中的React实例。
2. 验证Babel配置的正确性
确保你的Babel配置(.babelrc或者babel.config.js)正确处理了React语法,特别是Hook相关的转换。推荐的配置如下:
{ "presets": [ "@babel/preset-env", "@babel/preset-react" ], "plugins": [ "@babel/plugin-proposal-class-properties", "babel-plugin-styled-components" ] }
避免添加任何会修改Hook调用逻辑的额外插件,比如旧版本的transform-react-jsx(现在已经整合到preset-react中了)。
3. 避免npm/yarn link带来的潜在问题
虽然你已经确认没有多实例问题,但如果是通过npm link或者yarn link在CRA项目中测试组件库,可能还是会因为符号链接导致React实例重复。建议你通过npm pack生成组件库的tar包,然后在CRA项目中本地安装这个包来测试:
# 在组件库目录执行 npm pack # 在CRA项目目录执行 npm install ../react-ui-kit-0.0.15.tgz
最后验证
完成上述修改后,重新构建组件库:
npm run build
然后在CRA项目中更新依赖并重启开发服务器,应该就能正常使用带有useRef的组件了。
内容的提问来源于stack exchange,提问作者Morgan Yu

