使用npm link本地React组件库时遇dispatcher is null错误求助
错误根源
这个错误本质是本地项目同时加载了两个独立的React实例:
- 本地项目自身node_modules中的React
- 通过
npm link关联的组件库node_modules中的React
React Hook(比如报错栈里的useContext,被useTranslation依赖)依赖单一全局React上下文,多个实例会导致Hook无法找到正确的dispatcher,最终抛出dispatcher is null。
而发布后用yarn install能正常运行,是因为npm/yarn会自动扁平化依赖,确保整个项目只加载一份React实例。
修复方案
1. 完善组件库的peerDependencies配置
在组件库的package.json中添加peerDependencies,明确声明React相关依赖为对等依赖,告知使用方由其提供统一的实例:
"peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "react-i18next": "^12.1.1" }
你已在devDependencies中包含这些包,但peerDependencies需要单独声明,避免组件库加载自身的独立实例。
2. 强制本地项目使用单一React实例
在本地项目的构建配置中添加别名,强制解析React相关依赖时只使用项目自身的node_modules版本:
- 若使用自定义Webpack配置,修改
webpack.config.js:
const path = require('path'); module.exports = { resolve: { alias: { 'react': path.resolve(__dirname, 'node_modules/react'), 'react-dom': path.resolve(__dirname, 'node_modules/react-dom'), 'react-i18next': path.resolve(__dirname, 'node_modules/react-i18next') } } };
- 若使用Create React App,可借助
craco修改配置(安装@craco/craco后创建craco.config.js):
const path = require('path'); module.exports = { webpack: { alias: { 'react': path.resolve(__dirname, 'node_modules/react'), 'react-dom': path.resolve(__dirname, 'node_modules/react-dom'), 'react-i18next': path.resolve(__dirname, 'node_modules/react-i18next') } } };
3. 临时清理组件库node_modules(可选)
删除组件库的node_modules文件夹,这样npm link时组件库会直接复用本地项目的React依赖,彻底避免重复加载。测试完成后再重新执行npm install恢复组件库的开发依赖即可。
4. 验证修复
重新执行npm link关联组件库,重启本地项目开发服务器,检查错误是否消失。
补充说明
你的Rollup配置中已经使用rollup-plugin-peer-deps-external,这个插件会自动将peerDependencies中的包排除在打包产物外,这一步是正确的——发布后的包不会包含React等依赖,问题仅出现在npm link的本地开发场景(此时依赖未被npm/yarn扁平化处理)。
内容的提问来源于stack exchange,提问作者four-eyes

