I am using vite, TS to created a react component library.
My main.tsx in component-library contains the following test component,
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>;
};
The library build is created using tsc && vite build
and installed to an actual React project using npm install --save ../component-library
. Upon running the project I get the following error,
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
Its complaining on useState
. However I am able to see the log CONTENT-TEST
in the logs. Here is the code to the react app project,
import "./App.css";
import { TestComponent } from "component-library";
function App() {
return (
<div className="App">
<TestComponent />
</div>
);
}
export default App;
Can anyone please help resolve this issue?
EDIT: I should also mentioned that my react app is a javascript react project and not using TS and vite. It was created through CRA
Here is my vite config,
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"] })], });
Here are the peer dependencies form package.json. These dependencies have the same version as the CRA react app project,
"peerDependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
2
Answers
What worked for me was to create a React app with
npm create vite@latest
. One main difference is I am using TS and vite in this case and this seems to be compatible somehow and worked. I might actually check creating a React app with vite and JS and see if it works. If it works then the possible issue is in the packages installed by CRA as its dependencies.Check for peerDependency in component library package.json
And then we can validate this version is same in main react-app
We can re-install dependencies in both
npm install
In Component Library we can check React is marked as an external dependency in component library to avoid bundling it multiple times
We can do so in vite.config.ts for the component library
i. Run
npm dedupe
ii. Use Aliases in Webpack
After making these changes we can rebuild component library and reinstall it in the main application.
Reference for additional checks: https://github.com/facebook/react/issues/30520
https://www.dhiwise.com/post/how-to-resolve-the-error-react-dispatcher-is-null