React组件库在CRA项目中使用useState时出现dispatcher is null错误求助
解决Vite构建React组件库在CRA项目中运行时
dispatcher is null错误 问题背景
我用Vite+TypeScript开发了一个React组件库,其中TestComponent代码如下:
import React, { useState } from "react"; export const TestComponent = () => { console.log("CONTENT-TEST"); const [yamlTemplate, setYamlTemplate] = useState<string>("test component"); console.log("CONTENT", yamlTemplate); console.log("CONTENT-setTemplate", setYamlTemplate); return <div>Test Component</div>; };
通过tsc && vite build构建组件库后,用npm install --save ../component-library将其安装到CRA创建的JavaScript React项目中。运行项目时出现以下错误:
dispatcher is null useState@http://localhost:3000/static/js/bundle.js:2823:7 Qr@http://localhost:3000/static/js/bundle.js:46064:67 renderWithHooks@http://localhost:3000/static/js/bundle.js:22917:31
错误指向useState,但能看到CONTENT-TEST的日志输出。CRA项目中引入组件的代码:
import "./App.css"; import { TestComponent } from "component-library"; function App() { return ( <div className="App"> <TestComponent /> </div> ); } export default App;
组件库的Vite配置:
import { defineConfig } from "vite"; import dts from "vite-plugin-dts"; import { libInjectCss } from "vite-plugin-lib-inject-css"; import react from "@vitejs/plugin-react"; import path, { extname, relative, resolve } from "path"; import { fileURLToPath } from "node:url"; import { glob } from "glob"; export default defineConfig({ build: { copyPublicDir: false, lib: { entry: resolve(__dirname, "src/index.tsx"), formats: ["cjs", "es"], }, rollupOptions: { external: ["react", "react-dom"], input: Object.fromEntries( glob .sync("src/**/*.{ts,tsx}", { ignore: ["src/**/*.d.ts"], }) .map((file) => [ relative("src", file.slice(0, file.length - extname(file).length)), fileURLToPath(new URL(file, import.meta.url)), ]), ), output: { assetFileNames: "assets/[name][extname]", entryFileNames: "[name].js", globals: { react: 'React', 'react-dom': 'ReactDOM', }, }, }, sourcemap: true, emptyOutDir: true, }, plugins: [react(), libInjectCss(), dts({ include: ["src"] })], });
组件库package.json的peerDependencies与CRA项目React版本一致:
"peerDependencies": { "react": "^18.3.1", "react-dom": "^18.3.1" },
问题原因
这个错误本质是React重复加载:组件库构建或安装过程中,出现了两份独立的React实例——CRA项目的React和组件库本地依赖的React,导致Hooks无法正确关联到React的dispatcher。
解决步骤
1. 确保组件库仅依赖宿主项目的React
检查组件库的package.json,将react和react-dom从dependencies中移除(如果之前误加),只保留在peerDependencies中,同时添加peerDependenciesMeta明确依赖要求:
"peerDependencies": { "react": "^18.3.1", "react-dom": "^18.3.1" }, "peerDependenciesMeta": { "react": { "optional": false }, "react-dom": { "optional": false } }
2. 修正Vite构建配置,强化React外部化
调整Vite配置,确保React相关模块完全被外部化,并优化输出文件的识别性:
import { defineConfig } from "vite"; import dts from "vite-plugin-dts"; import { libInjectCss } from "vite-plugin-lib-inject-css"; import react from "@vitejs/plugin-react"; import path, { resolve } from "path"; export default defineConfig({ build: { copyPublicDir: false, lib: { entry: resolve(__dirname, "src/index.tsx"), formats: ["cjs", "es"], fileName: (format) => `component-library.${format}.js`, }, rollupOptions: { // 精确外部化React所有相关模块 external: ["react", "react-dom", /^react\/.*/, /^react-dom\/.*/], output: { assetFileNames: "assets/[name][extname]", globals: { react: 'React', 'react-dom': 'ReactDOM', }, }, }, sourcemap: true, emptyOutDir: true, }, plugins: [react(), libInjectCss(), dts({ include: ["src"] })], });
同时在组件库package.json中明确指定入口文件:
"main": "./dist/component-library.cjs.js", "module": "./dist/component-library.es.js", "types": "./dist/index.d.ts", "files": [ "dist" ]
3. 清理重复依赖并重新安装
- 卸载CRA项目中的组件库:
npm uninstall component-library - 删除CRA项目的
node_modules、package-lock.json(或yarn.lock) - 组件库重新构建:
vite build(无需单独执行tsc,vite-plugin-dts已处理类型声明) - 重新安装组件库到CRA项目:
npm install --save ../component-library - 在CRA项目根目录执行
npm ls react,确认输出中只有一个React版本实例
4. 验证修复
启动CRA项目,检查TestComponent是否正常渲染,控制台是否不再出现dispatcher is null错误。
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

