0

I'm currently working on my first gatsby/react/typescript project and one of the requirements is to create a component library which should hold components commonly used in the upcoming applications.

My inital test with only one component (without the index.ts as the entry was the FancyBanner.tsx itself) worked. After adding a second component (FancyButton.tsx) and the index.ts, I can not use the component in my App. Following error occures:

Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Setup

  • Gatsby 2
  • React 16.5
  • Typescript 3
  • Local npm registry through Artifactory

Project structure (this is the stipped down version as the gatsby files is only needed for testing an not relevant built component library)

component-lib/
  src/
    lib/
      fancy.css
      FancyButton.tsx
      FancyBanner.tsx
    index.ts
  index.d.ts
  package.json
  tsconfig.json
  webpack.config.js 

The two components are nearly identical but should replicate two individual components:

import * as React from 'react';
import './fancy.css'

interface Props {
    text: string
}

interface State {
    /* no state required */
}

export default class FancyBanner extends React.Component<Props, State> {

    public static defaultProps: Partial<Props> = {
        text: "this is a fancy component"
    };

    public render() {
        return (
            <div className={"fancy"}>
                {this.props.text}
            </div>
        );
    };
}

-

import * as React from 'react';
import './fancy.css'

interface Props {
    text: string
}

interface State {
    /* no state required */
}

export default class FancyButton extends React.Component<Props, State> {

    public static defaultProps: Partial<Props> = {
        text: "this is a fancy button"
    };

    public render() {
        return (
            <div className={"button fancy"}>
                {this.props.text}
            </div>
        );
    };
}

The index.ts simply exports the two componets

export * from "./fancy/FancyButton"
export * from "./fancy/FancyBanner"

The index.d.ts is "handmade" (maybe this is the problem?)

import * as React from "react";

export interface Props {
    text: string;
}

export interface State {
}

export class FancyBanner extends React.Component<Props, State> {}

export class FancyButton extends React.Component<Props, State> {}

Finally, the different configuration files

{
  "name": "company-component-lib",
  "description": "makes your app fancy",
  "version": "0.0.7-snapshot.10",
  "main": "dist/bundle.js",
  "types": "index.d.ts",
  "dependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack --watch",
    "build": "webpack",
    "local-release": "npm run build && npm link",
    "release": "npm run build && npm publish"
  },
  "devDependencies": {
    "@types/node": "^10.10.3",
    "@types/react": "^16.4.14",
    "@types/react-dom": "^16.0.7",
    "react": "^16.5.2",
    "react-dom": "^16.5.2",
    "react-helmet": "^5.2.0",
    "typescript": "^3.0.3",
    "css-loader": "^1.0.0",
    "gatsby": "^2.0.8",
    "gatsby-link": "^2.0.1",
    "gatsby-plugin-react-helmet": "^3.0.0",
    "gatsby-plugin-typescript": "^2.0.0",
    "style-loader": "^0.23.0",
    "webpack-cli": "^3.1.1",
    "ts-loader": "^5.2.1"
  },
  "publishConfig": {
    "type": "npm",
    "registry": "<myrepo>"
  },
  "files": [
    "dist/bundle.js",
    "index.d.ts"
  ]
}

-

{
  "compilerOptions": {
    "outDir": "./dist/",
    "module": "commonjs",
    "target": "es5",
    "jsx": "react",
    "declaration": true,
    "lib": ["dom", "es5"]
  },
  "include": [
    "./src/lib/**/*"
  ]
}

-

var path = require('path');

module.exports = {
    entry: './src/lib/index.ts',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        libraryTarget: 'commonjs2'
    },
    module: {
        rules: [
            {
                test: /\.tsx$/,
                include: path.resolve(__dirname, 'src/lib'),
                exclude: /(node_modules|bower_components|public)/,
                use: 'ts-loader'
            },
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            }
        ]
    },
    externals: {
        'react': 'commonjs react'
    },
    resolve: {
        extensions: [".tsx", ".ts", ".js"]
    }
};

After build and publish I can install my component library in my app and IntelliJ automatically adds the import

import * as React from 'react'
import Layout from "../components/layout";
import {FancyBanner} from "company-component-lib";

export default class Page_7 extends React.Component<any, any> {

    public render() {
        return (
            <Layout>
                <div>
                    <h1>Component Sample Page</h1>

                    <FancyBanner text={"WOOOHOOO!"}/>

                </div>
            </Layout>
        )
    }
}

I tried some of the suggestions from this quests but the error remains. As a react/typescript newby I somewhat have the feeling that the typescript declaration is the problem but cannot find the failure in my setup. Any hints or suggestions are appreciated.

##### UPDATE #####

After further research we dropped webpack with babel and simply use tsc based on this tutorial. This tutorial helped us to create a commons library but sadly does not answer the intial question, why the module with webpack and babel cannot be imported (specificaly what we did wrong and if webpack with babel is suitable for this scenario).

Patrick
  • 55
  • 1
  • 7
  • You don't need `index.d.ts`. to know more about how to import and export module see link https://www.typescriptlang.org/docs/handbook/modules.html – Juned Lanja Oct 03 '18 at 10:50
  • thank you @JunedLanja for your quick response. can you elaborate more on the "you don't need index.d.ts" part, because I'm using `webpack` to create a `bundle.js` and when I remove the `d.ts file`, publish, install and trying to use the library, IntelliJ find/import it .. maybe my webpack configuration is not right? do I miss some steps/files before the build process? – Patrick Oct 03 '18 at 11:13

0 Answers0