Search code examples
javascriptreactjstypescriptrollupjs

JSX element type '<Component>' does not have any construct or call signatures error AND MORE


I've been beating my head against a wall for days, so I'm throwing myself on the mercy of people who are smarter than me.

(Sorry for the length... I'm trying to be thorough)

I'm currently working a small app where I'm using a component library I'm developing myself. I'm connecting to the library locally using "@name/library": "link:/path/to/library" in the package.json in my app. I'm exporting the components from the library using barrel files (hate me if you want). I'm also using rollup as my bundler for the library. Starting from the library component on up they look like this:

library/src/components/FormElements/FormTextInput.tsx

import FormInputLabel from './FormInputLabel';

type FormTextInputProps = {
  label?: string;
  name?: string;
  type?: 'text' | 'password' | 'number';
  labelPos?: 'left' | 'right' | 'above' | 'below';
  value?: string | number;
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
};

const FormTextInput: React.FC<FormTextInputProps> = ({
  label = '',
  name = '',
  type = 'text',
  labelPos = 'left',
  value = '',
  onChange
}) => {
  const onChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    onChange?.(e);
  };

  return (
    <div>
      {labelPos === 'left' || labelPos === 'above' ? (
        <FormInputLabel position={labelPos} name={name} label={label} />
      ) : (
        ''
      )}
      <input
        value={value}
        type={type}
        name={name}
        id={name}
        onChange={onChangeHandler}
      />
      {labelPos === 'right' || labelPos === 'below' ? (
        <FormInputLabel position={labelPos} name={name} label={label} />
      ) : (
        ''
      )}
    </div>
  );
};

export default FormTextInput;

library/src/components/FormElements/index.ts

export { default as FormInputLabel } from './FormInputLabel';
export { default as FormTextInput } from './FormTextInput';

library/src/components/index.ts

export * from "./FormElements";

library/src/index.ts

export * from "./components";

Here's the component in my app, consumes it (collapsed):

MovieEditor.tsx

import { useQuery, useMutation } from '@apollo/client';
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { useLocation } from 'react-router-dom';
import { GET_MOVIE } from './queries';
import { ADD_MOVIE, UPDATE_MOVIE } from './mutations';
import FormTextInput from '@name/library'; <-- No complaints about import

.......

const MovieEditor: React.FC = () => {
  
     ...........

  return (
    <>
      <h3 className="text-lg font-semibold p-4">Create/Update Movie</h3>
      <FormTextInput label="Not Working" /> <-- Errors here
      <form ...
      </form>
    </>
  );
};

export default MovieEditor;

Here are the errors I'm getting - Both on the same line:

  • JSX element type 'FormTextInput' does not have any construct or call signatures.ts(2604)
  • 'FormTextInput' cannot be used as a JSX component. Its type 'typeof import("/home/collin/Git/phantomartist/dist/index")' is not a valid JSX element type.ts(2786)

Don't know if this helps, but here is my rollup.config.mjs file:

import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import typescript from "@rollup/plugin-typescript";
import dts from "rollup-plugin-dts";

import packageJson from "./package.json" assert { type: "json" };

export default [
  {
    input: "src/index.ts",
    output: [
      {
        file: packageJson.main,
        format: "cjs",
        sourcemap: true,
      },
      {
        file: packageJson.module,
        format: "esm",
        sourcemap: true,
      },
    ],
    plugins: [
      resolve(),
      commonjs(),
      typescript({ tsconfig: "./tsconfig.json" }),
    ],
  },
  {
    input: "dist/ems/types/index.d.ts",
    output: [{ file: "dist/index.d.ts", format: "esm" }],
    plugins: [dts()],
  },
];

And my package.json for the library:

{
  "name": "@name/library",
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/name"
  },
  "version": "0.0.0",
  "type": "module",
  "module": "dist/ems/index.js",
  "main": "dist/cjs/index.js",
  "files": [
    "dist"
  ],
  "types": "dist/index.d.ts",
  "scripts": {
    "rollup": "rollup -c",
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "@rollup/plugin-commonjs": "^26.0.1",
    "@rollup/plugin-terser": "^0.4.4",
    "@stylexjs/stylex": "^0.7.5",
    "react": "^18.3.0",
    "react-dom": "^18.3.0"
  },
  "devDependencies": {
    "@rollup/plugin-node-resolve": "^15.2.3",
    "@rollup/plugin-typescript": "^11.1.6",
    "@types/react": "^18.3.0",
    "@types/react-dom": "^18.3.0",
    "@typescript-eslint/eslint-plugin": "^7.13.1",
    "@typescript-eslint/parser": "^7.13.1",
    "@vitejs/plugin-react": "^4.3.1",
    "eslint": "^8.57.0",
    "eslint-plugin-react-hooks": "^4.6.2",
    "eslint-plugin-react-refresh": "^0.4.7",
    "react": "^18.3.1",
    "rollup": "^4.18.0",
    "rollup-plugin-dts": "^6.1.1",
    "tslib": "^2.6.3",
    "typescript": "^5.2.2",
    "vite": "^5.3.1"
  },
  "peerDependencies": {
    "react": "^18.3.1"
  }
}

When I try import FormTextInput from '@name/library/src/components/FormElements/FormTextInput.tsx it works like a champ.

I have tried every possible permutations of making those barrel files. I've checked spelling 1000 times (I really hope this isn't the problem 😅). I have Googled and tried every suggestion under the sun. Codeium hasn't be very helpful -- Just tells me to do what I've already tried.

And if you know a better way to do what I'm tying to do, feel free to drop that on me as well.

Please! Someone! Be my hero!


Solution

  • It is a default export in library/src/components/FormElements/FormTextInput.tsx so if you import it like import FormTextInput from '@name/library/src/components/FormElements/FormTextInput.tsx' it works.

    However, in library/src/components/FormElements/index.ts you have export { default as FormTextInput } from './FormTextInput'; which means it's re-exported as a named export FormTextInput.
    Then you have export * statements in library/src/components/index.ts, and again in library/src/index.ts so FormTextInput is also a named export there, and should be imported like import { FormTextInput } from '@name/library'.

    There error you saw occurred because you tried using a default export from library/src/index.ts (which was probably something else, and it has no construct or call signatures).