jwir3
jwir3

Reputation: 6219

Importing a component library using react in Storybook

I have two projects: one is a component library called simply '@loonslanding/components'. The other is a storybook project. Inside of the components library, I have the following in src/index.js:

import React, { Component } from 'react';

class Button extends Component {
  render () {
    return (
      <button>{this.props.label}</button>
    );
  }
}

export default Button;

I build this using webpack and babel with the following webpack.config.js:

const path = require('path');

module.exports = {
  entry: './src/index.js',
  mode: 'development',
  output: {
    filename: 'index.bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      },
      {
        test: /\.s[ac]ss$/i,
        use: [
          // Creates `style` nodes from JS strings
          'style-loader',
          // Translates CSS into CommonJS
          'css-loader',
          // Compiles Sass to CSS
          'sass-loader',
        ],
      }
    ]
  }
};

I then link my js module using yarn link in the components directory and run yarn link @loonslanding/components in my storybook directory. I have a single story in storybook, called button.stories.js:

import Button from "@loonslanding/components";

import { action } from '@storybook/addon-actions';

import React from 'react';

export default {
  component: Button,
  title: `Atoms/Button`
};

export const Standard = () => <Button onClick={action('clicked')} label={"Standard Button"}></Button>;

When I run yarn storybook, I get the following error message:

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

Check the render method of `storyFn`.

This seems like a pretty common error, and I've researched it over the past few hours, but I don't think I've actually mixed up named and default exports/imports. When I attempt to import the components project into a different project (e.g. a react application other than Storybook), it gives me a similar exception. This leads me to believe that something is wonky with how Babel is transpiling the components module. Thoughts on what I might be doing incorrectly?

Upvotes: 1

Views: 3151

Answers (1)

jwir3
jwir3

Reputation: 6219

This was due to having incorrect parameters in the Webpack configuration file. I learned from this answer that Webpack is designed to package applications by default, and if you want it to package a library, you need to add the library name, as well as the library target type. This looks like the following when using the commonjs2 library target type:

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const nodeExternals = require('webpack-node-externals');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'index.js',
    path: path.resolve(__dirname, 'dist'),
    library: 'loonslandingstorybook',
    libraryTarget: 'commonjs2'
  },
  plugins: [new CleanWebpackPlugin()],
  module: {
    rules: [
     {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            plugins: ['@babel/plugin-transform-react-jsx']
          }
        }
      },
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
        include: path.resolve(__dirname, './src')
      }
    ]
  }
}

Upvotes: 1

Related Questions