Search code examples
reactjsreact-hooksvitebundler

React Component Library - dispatcher is null useState upon running in React app


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"
  },

Solution

  • 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.