react-docgen-typescript-loader icon indicating copy to clipboard operation
react-docgen-typescript-loader copied to clipboard

No propTypes defined! when using create-react-app and babel-loader 8.0.4

Open aloifolia opened this issue 6 years ago • 33 comments

I created a test project with create-react-app, added Typescript and Storybook by following the recommendations in the following storybook issue:

https://github.com/storybooks/storybook/issues/4739

Then I added the docgen generator as described here:

https://storybook.js.org/configurations/typescript-config/

This left me with following files.

webpack.config.js:

const path = require('path');
const TSDocgenPlugin = require('react-docgen-typescript-webpack-plugin');
module.exports = (baseConfig, env, config) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('awesome-typescript-loader'),
  });
  config.plugins.push(new TSDocgenPlugin()); // optional
  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};

package.json:

{
  "name": "react-demo-ts",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@storybook/addon-knobs": "^4.0.7",
    "@types/jest": "^23.3.9",
    "@types/node": "^10.12.8",
    "@types/react": "^16.7.6",
    "@types/react-dom": "^16.0.9",
    "react": "^16.6.3",
    "react-dom": "^16.6.3",
    "react-scripts": "2.1.1",
    "typescript": "^3.1.6"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "storybook": "start-storybook -p 9009 -s public",
    "build-storybook": "build-storybook -s public"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ],
  "devDependencies": {
    "@storybook/addon-actions": "^4.0.7",
    "@storybook/addon-info": "^4.0.7",
    "@storybook/addon-links": "^4.0.7",
    "@storybook/react": "^4.0.7",
    "@types/storybook__addon-actions": "^3.4.1",
    "@types/storybook__addon-info": "^3.4.2",
    "@types/storybook__addon-knobs": "^3.4.1",
    "@types/storybook__addon-links": "^3.3.2",
    "@types/storybook__react": "^4.0.0",
    "babel-loader": "^8.0.4",
    "fork-ts-checker-webpack-plugin": "^0.4.15",
    "react-docgen-typescript-loader": "^3.0.0",
    "react-docgen-typescript-webpack-plugin": "^1.1.0"
  }
}

The result looks like this: screen shot 2018-11-16 at 00 05 27

I guess this issue might be related to https://github.com/strothj/react-docgen-typescript-loader/issues/23. Any idea how to solve it?

aloifolia avatar Nov 15 '18 23:11 aloifolia

Unfortunately the Storybook docs are out of date.

Try this

const path = require('path')

/**
 *
 * @param baseConfig
 * @param env
 * @param {webpack.Configuration} config
 * @return {webpack.Configuration}
 */
module.exports = (baseConfig, env, config) => {
	// TypeScript support
	config.module.rules.push({
		test: /\.(ts|tsx)$/,
		include: path.resolve(__dirname, '../src'),
		use: [
			{
				loader: require.resolve('ts-loader'),
				options: {
					transpileOnly: true,
				},
			},
			require.resolve('react-docgen-typescript-loader'),
		],
	})
	config.resolve.extensions.push('.ts', '.tsx')

	return config
}
{
  "compilerOptions": {
    "outDir": "build",
    "module": "esnext",
    "target": "es5",
    "lib": [
      "es6",
      "esnext",
      "dom"
    ],
    "jsx": "react",
    "moduleResolution": "node",
    "declaration": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "sourceMap": true,
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "allowJs": true
  },
  "include": [
    "src/**/*",
    ".storybook/*"
  ]
}

OzairP avatar Nov 17 '18 18:11 OzairP

So... is the second code block meant to be added to the file tsconfig.json in the app folder? In .storybook, there is another tsconfig.json. Should I change it, as well? If I don't do it, I get the following error message now:

Error: Module build failed (from ../node_modules/ts-loader/index.js):
Error: Cannot find module 'typescript'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
    at Function.Module._load (internal/modules/cjs/loader.js:507:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at Object.<anonymous> (/path/to/my/project/node_modules/ts-loader/dist/utils.js:6:20)
    at Module._compile (internal/modules/cjs/loader.js:689:30)

aloifolia avatar Nov 19 '18 17:11 aloifolia

I was able to get this to work using CRA and babel-loader. Here is my complete config:

// .storybook/webpack.config.js
const path = require('path');

module.exports = (_baseConfig, _env, config) => {
  config.node = {
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
  };

  config.module.rules.push({
    test: /\.tsx?$/,
    include: path.resolve(__dirname, '../src'),
    use: [
      {
        loader: require.resolve('babel-loader'),
        options: {
          presets: [require.resolve('babel-preset-react-app')],
        },
      },
      require.resolve('react-docgen-typescript-loader'),
    ],
  });

  config.resolve.extensions.push('.ts', '.tsx');

  return config;
};
// .storybook/config.js
import { configure, addDecorator } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';

function loadStories() {
  addDecorator(withInfo);
  require('../src/stories/index.stories.tsx');
}

configure(loadStories, module);
// src/stories/index.stories.tsx
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
...

storiesOf('My Component', module)
  .add('foo', () => {
    return <MyComponent names={['Bill', 'Sandra']} status="online" />;
  }, { info: { inline: true } });

stevehanson avatar Nov 19 '18 21:11 stevehanson

This works for me, thank you! It would be good to have this in the official documentation.

aloifolia avatar Nov 23 '18 13:11 aloifolia

~~@aloifolia @stevehanson Not working for me, the only doc that displays is the component description, but No propTypes defined~~

~~Edit: Turns out it does work but only with classes, doesn't work with SFC's.~~

~~Edit 2: As it further turns out it works with SFC's if I remove or comment out the "esModuleInterop": true line from tsconfig.json~~

Also I've been notified that the term "SFC"(Stateless Functional Components) is being deprecated since Hooks can add state to functional components.

Edit 3: Further test showed that it was me using React.SFC/React.FunctionComponent instead of SFC or FunctionComponent that caused it as stated in the react-docgen-typescript readme. For some reason I previously assumed this was only an issue when using classes.

Dudeonyx avatar Nov 26 '18 17:11 Dudeonyx

Does anyone have a fully working, minimal example repo of this that they can share? Perhaps we could link to it in the docs.

teddybradford avatar Feb 10 '19 18:02 teddybradford

Thank you @stevehanson for your solution! @teddybradford I created a full sample repo that others can use, could be linked to in the documentation I guess :) https://github.com/johot/storybook4-cra2-typescript-react-docgen-typescript-demo

johot avatar Feb 14 '19 21:02 johot

@stevehanson (or anyone else), what is the reason you need to add

options: {
  presets: [require.resolve('babel-preset-react-app')],
},

to make this work? I tried removing it and it stopped working (wanting something as close to the official docs as possible). Just want to understand fully 😄

johot avatar Feb 15 '19 08:02 johot

@stevehanson (or anyone else), what is the reason you need to add

options: {
  presets: [require.resolve('babel-preset-react-app')],
},

to make this work? I tried removing it and it stopped working (wanting something as close to the official docs as possible). Just want to understand fully

That has to do with the way dependencies are resolved. Whether or not passing a naked babel-preset-react-app works depends on the dependency tree and how many copies of Webpack there are.

If you pass resolve('babel-preset-react-app') then the path to the dependency will be passed to Webpack from the context of the config file which will have access to the root dependencies of your workspace.

strothj avatar Feb 15 '19 15:02 strothj

Thank you @stevehanson for your solution! @teddybradford I created a full sample repo that others can use, could be linked to in the documentation I guess :) https://github.com/johot/storybook4-cra2-typescript-react-docgen-typescript-demo

@johot

Do you mind if I pull this into the examples in the repo?

strothj avatar Feb 15 '19 15:02 strothj

Thank you @stevehanson for your solution! @teddybradford I created a full sample repo that others can use, could be linked to in the documentation I guess :) https://github.com/johot/storybook4-cra2-typescript-react-docgen-typescript-demo

@johot

Do you mind if I pull this into the examples in the repo?

Sure go ahead!

johot avatar Feb 18 '19 09:02 johot

I've tried @stevehanson's solution above but no luck. Am I missing something? My configuration seems the same as above, but I keep getting "No propTypes defined!"

// .storybook/webpack.config.js
module.exports = ({ config }) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    use: [
      {
        loader: require.resolve('babel-loader'),
        options: {
          presets: [require.resolve('babel-preset-react-app')],
        },
      },
      require.resolve('react-docgen-typescript-loader'),
    ],
  });

  config.resolve.extensions.push('.ts', '.tsx');

  return config;
};
// .storybook/config.js
import { addDecorator, configure } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';
import { withInfo } from '@storybook/addon-info';

addDecorator(withKnobs);
addDecorator(withInfo);

const req = require.context('../', true, /\.stories\.tsx$/);

function loadStories() {
  req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);
// components/Button/Button.stories.tsx
import * as React from 'react';
import { storiesOf } from '@storybook/react';
import { text } from '@storybook/addon-knobs';
import Button from './Button';

storiesOf('Button', module)
  .add('default', () => <Button>{text('Text', 'Hello World')}</Button>, {
    info: { inline: true },
  });
// components/Button/Button.tsx
import React from 'react';
import cx from 'classnames';

const styles = require('./Button.module.scss');

interface Props {
  type?: 'button' | 'submit' | 'reset';
  clearDefaultButtonStyle?: boolean;
}

/* eslint-disable react/button-has-type */

const Button: React.StatelessComponent<Props> = ({
  children,
  clearDefaultButtonStyle,
  type = 'button',
}) => (
  <span
    className={cx({
      [styles.clearDefaultButtonStyles]: clearDefaultButtonStyle,
    })}
  >
    <button type={type}>{children}</button>
  </span>
);

export default Button;

mattdell avatar Mar 27 '19 16:03 mattdell

We have an almost identical setup as @mattdell and have the same problem. All of our props show up as No Proptypes defined.

We aren't using CRA however and so our webpack looks like this:

const path = require('path');

module.exports = ({ config, mode }) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    include: path.resolve(__dirname, "../stories"),
    use: [
      {
        loader: require.resolve('babel-loader'),
        options: {
          presets: [require.resolve('@babel/preset-react'), require.resolve('@babel/preset-typescript')],
        }
      },
      require.resolve("react-docgen-typescript-loader"),
    ]
  });
  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};

Also worth mentioning is that we are using a monorepo and importing our components from another package into our storybook application.

draftitchris avatar Apr 11 '19 19:04 draftitchris

We are also using a monorepo, not sure if that is the issue, but i noticed that when I use addDecorator directly after storiesOf, it actually shows the typings for Story:

# Prop Types
## "AUDIOPLAYER" COMPONENT
No propTypes defined!

## "STORY" COMPONENT
property | propType | required | default | description
-- | -- | -- | -- | --
context | other | - | null |  
info | other | - |   |  
propTables | other | - | null |  
propTablesExclude | other | - | [] |  
showInline | bool | - | false |  
showHeader | bool | - | true |  
showSource | bool | - | true |  
styles | func | yes | - |  
children | other | - | null |  
components | other | - | {} |  
maxPropsIntoLine | number | yes | - |  
maxPropObjectKeys | number | yes | - |  
maxPropArrayLength | number | yes | - |  
maxPropStringLength | number | yes | - |  
excludedPropTypes | other | - | []

Here is my index.stories.tsx:

import React from "react";
import { AudioPlayer } from "./";
import { storiesOf } from "@storybook/react";
import { withInfo } from "@storybook/addon-info";

const clip = "http://dare.wisc.edu/sites/dare.wisc.edu/files/HI009clip.mp3";

storiesOf("AudioPlayer", module)
  .addDecorator(withInfo)
  .add("hawaii clip", () => <AudioPlayer src={clip} />, {
    info: { inline: true }
  })
  .add("with duration", () => <AudioPlayer src={clip} />, {
    info: { inline: true }
  });

ianks avatar Apr 11 '19 22:04 ianks

Ok I found the solution for us. If you are writing your stories using typescript, you need to make sure the the react-docgen-typescript-loader is does not run for .stories.tsx files.

Here is what our babel-loader is:

  {
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          // make sure not to compile story files!
          exclude: [/node_modules/, /\.stories\.tsx$/, /__tests__/],
          use: [
            {
              loader: "babel-loader",
              options: {
                configFile: require.resolve("@franchises/common/babel-config"),
                plugins: [!opts.cold && "react-hot-loader/babel"].filter(
                  Boolean
                )
              }
            },
            opts.docgen && require.resolve("react-docgen-typescript-loader")
          ].filter(Boolean)
        },
        // If you want to use typescript for your stores, add this section
        {
          test: /\.stories\.tsx?$/,
          exclude: [/node_modules/, /__tests__/],
          use: [
            {
              loader: "babel-loader",
              options: {
                configFile: require.resolve("@franchises/common/babel-config")
              }
            }
          ]
        }
      ]
    }
  }

ianks avatar Apr 11 '19 22:04 ianks

Try import React, { Component } from "react" and const Button: StatelessComponent instead of using const Button: React.StatelessComponent. I recall reading someone saying that made a difference, but I'm not sure why or how it would. 😕

No difference. 😕

mattdell avatar Apr 12 '19 09:04 mattdell

This is working for me:

webpack.config.js

module.exports = ({ config, mode }) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    use: [
      {
        loader: require.resolve('babel-loader'),
        options: {
          presets: [['react-app', { flow: false, typescript: true }]],
        },
      },
      {
        loader: require.resolve('react-docgen-typescript-loader'),
      },
    ],
  });
  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};

ColorButton.tsx

import * as React from 'react';

interface ColorButtonProps {
  /** Buttons background color */
  color: 'blue' | 'green';
}

/** A button with a configurable background color. */
export const ColorButton: React.SFC<ColorButtonProps> = (props) => (
  <button
    style={{
      padding: 40,
      color: '#eee',
      backgroundColor: props.color,
      fontSize: '2rem',
    }}
  >
    {props.children}
  </button>
);

export default ColorButton;

stories/index.js

storiesOf('Components', module).add(
  'ColorButton',
  withInfo({ inline: true })(() => (
    <ColorButton color="blue">Color Button</ColorButton>
  )),
);

chrisahardie avatar Apr 12 '19 14:04 chrisahardie

I was having this issue and realized the culprit was the way I was importing the component to my story.

My directory: src/ src/index.tsx /src/Button /src/Button/button.tsx

My component in button.tsx looked like this:

import React from "react";

interface IProps {
  /**
   * Text for the button
   */
  text: string | JSX.Element;
  /**
   * Callback function for actions
   */
  onClick?: () => undefined;
}

const Button = ({
  text,
  onClick
}: IProps) => {
  const style = {
    cursor: "pointer"
  };
  return (
    <a
      style={style}
      onClick={onClick}
    >
      {text}
    </a>
  );
};

export default Button;

Which I changed to this:

import React from "react";

interface IProps {
  /**
   * Text for the button
   */
  text: string | JSX.Element;
  /**
   * Callback function for actions
   */
  onClick?: () => undefined;
}

export const Button = ({
  text,
  onClick
}: IProps) => {
  const style = {
    cursor: "pointer"
  };
  return (
    <a
      style={style}
      onClick={onClick}
    >
      {text}
    </a>
  );
};

... and I was exporting from src/index.tsx like this:

import Button from "./Button/button";
export { Button };

Which I changed to this:

import { Button } from "./Button/button";
export { Button };

Then finally, in my button.stories.tsx, changing my import to this:

import { Button } from "../src";

... resolved my issue

dclark27 avatar Apr 12 '19 15:04 dclark27

Ok so I realized something very obvious that was dumb of us to miss. We are also importing our components but from a separate package in our monorepo. So of course the dockgen plugin wasn't doing anything in our stories package. There are no components there to compile! I added the docgen to our component library package so the output from there is compiled with the docgen plugin and all is well again.

Nothing to do with how we were exporting our components. Although I'm pretty sure in the docs it explicitly states that all components need to have a named export.

So to reiterate we have our webpack in our stories package:

const path = require('path');

module.exports = ({ config, mode }) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    include: path.resolve(__dirname, "../stories"),
    use: [
      {
        loader: require.resolve('babel-loader'),
        options: {
          presets: [require.resolve('@babel/preset-react'), require.resolve('@babel/preset-typescript')]
        }
      }
    ]
  });
  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};

and then we have our webpack in our component library package:

const path = require('path');

module.exports = {
    entry: { "index": path.resolve(__dirname, '../src/index.ts') },
    mode: "development",
    output: {
        path: path.resolve(__dirname, '../lib'),
        filename: '[name].js',
        library: "@app/ui",
        libraryTarget: 'umd'
    },
    resolve: {
        extensions: ['.ts', '.tsx', '.js']
    },
    externals: {
        'react': 'react',
        'react-dom': 'reactDOM',
        "styled-components": "styled-components"
    },
    devtool: "source-map",
    module: {
        rules: [
            {
                test: /\.(ts|tsx)$/,
                exclude: /node_modules/,
                include: path.resolve(__dirname, '../src'),
                use: [
                    {
                        loader: require.resolve('ts-loader')
                    },
                    require.resolve("react-docgen-typescript-loader"),
                ]
            }
        ]
    }
}

An example of a component looks like this:

import * as React from 'react';
import styled from 'styled-components';

export interface IButton extends IButtonStyle {
  /**
   * text
   */
  text?: string;
  /**
   * Button action
   */
  action: () => void
}
export interface IButtonStyle {
  /**
   * color
   */
  color?: string;
  /**
   * background color
   */
  bgColor?: string;
}

const StyledButton = styled.button<IButtonStyle>`
  background-color : ${props => props.bgColor};
  color: ${props => props.theme.palette.primary["500"]};
  border-radius: 2px;
  height: 2em;
  font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
  border-width: 1px;
  border-color: ${props => props.color};
`;

export const Button: React.FunctionComponent<IButton> = ({ text = 'defaultText', ...props }: IButton) => {
  return (
    <StyledButton onClick={props.action} color={props.color} bgColor={props.bgColor}>{text}</StyledButton>
  )
};

Button.displayName = "Button";

when we run webpack it compiles all of our d.ts files and components into alib/index.js and index.d.ts which is then consumable by our stories package. Here is an example of importing the button for the button story:

import * as React from 'react';
import { storiesOf } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';
import { Button } from '@app/ui-components';

const action = () => { console.log('Hey!') };

const stories = storiesOf("Components", module);

stories.add('Button', () => (
  <Button action={action} color="blue" text="hello world" bgColor="white" />
)); 

and everything works wonderfully :).

draftitchris avatar Apr 15 '19 14:04 draftitchris

For me work this method https://github.com/strothj/react-docgen-typescript-loader/issues/33#issuecomment-440045586

with this webpack.config.js

module.exports = ({config}) => {
    config.module.rules.push({
        test: /\.(ts|tsx)$/,
        use: [
            {
                loader: require.resolve('babel-loader'),
                options: {
                    presets: [['react-app', { flow: false, typescript: true }]],
                },
            },
            require.resolve('react-docgen-typescript-loader'),
        ],
    });

    config.resolve.extensions.push('.ts', '.tsx');

    return config;
};

minya92 avatar Jun 14 '19 07:06 minya92

I feel like I've tried everything in this thread. My code sample is above if anyone is able to have a look.

I'm using @storybook/react version 5.1.9. The example repo above is for Storybook 4. I wonder if there's a different solution for version 5?

mattdell avatar Jun 26 '19 11:06 mattdell

@mattdell Do you have a repo that reproduces the issue that I could look at?

draftitchris avatar Jun 26 '19 11:06 draftitchris

My problem ended up being that instead of import * as React from 'react' I had written import React from 'react', in case this helps anyone else.

jdherder avatar Jul 15 '19 17:07 jdherder

I've finally figured out my problem! I noticed that one of my components was working and through trial and error managed to figure out the cause.

The component that works was defined as such...

const Foo = ({ prop1, prop2 }: Props) => ( ... )

The one that does not work was defined like this...

const Foo: React.FunctionComponent<Props> = ({ prop1, prop2, children }) => ( ... )

This is because the first component is defined without children and the second prop uses children. My understanding is that using React.FunctionComponent<Props> is the best practice when using TypeScript and children rather than adding children: any to my Props interface.

Although this does allow it to work for this case, I don't want to have to implement children: any to my component interfaces when there's already a convention for this provided by React.

Any thoughts on why this issue occurs?

Tagging @draftitchris

mattdell avatar Jul 17 '19 13:07 mattdell

Is no one else using React.FunctionComponent?

mattdell avatar Aug 06 '19 11:08 mattdell

Sorry I totally forgot about this thread. We use React.FunctionComponent (now React.FC, but same thing) without any problems. You don't have to explicitly declare children unless you are using children btw. Ex:

const CompNotUsingChildren : React.FC<{prop1:string}> = ({prop1}) => <div>{prop1}</div>;

const CompUsingChildren : React.FC<{prop1:string, children}> = ({prop1, children}) => <div><h1>{prop1}</h1>{children}</div>

or 

interface Props{
   prop1: string;
}

const CompUsingChildren : React.FC<Props> =  (props) => <div><h1>{props.prop1}</h1>{props.children}</div>

It shouldn't affect the way docgen emits to storybook as far as I can tell. Its really hard to guess without seeing it as a whole.... right now we've been refactoring a lot so our info in storybook is disabled but it will be fixed in the near future... hopefully I can provide some more insight then. As for now without some sort of repo to reproduce your problem its hard to say.

draftitchris avatar Aug 06 '19 11:08 draftitchris

@mattdell same thing for me, React.FunctionComponent/React.FC does not work for me.

const Foo = ({ prop1, prop2 }: Props) => ( ... ) works fine though.

mauriciomelo avatar Aug 13 '19 11:08 mauriciomelo

Am working on a PR to reinstate this addon into our storybook now in our library and was able to get it working no problems with React.FunctionComponent/React.FC

I am just looking over your earlier configuration and noticed two things.

  1. You should declare addDecorator(withInfo) before (withKnobs) as stated in the git repo.
  2. You should be using React.FC and not StatelessComponent.

I am assuming you've done this already though its impossible to tell without an update example or a link to a repo that I can look at.

Another thing worth mentioning is that if you don't have your webpack.config in the root you might need to tell react-docgen-typescript-loader to find your tsconfig file.

Ex: (if your webpack.config file is one level down from your root, aka ./webpack/webpack.config.js)

{
    loader: require.resolve("react-docgen-typescript-loader"),
    options: {
        tsconfigPath: path.join(__dirname, "../tsconfig.json"),
    },
},

You could also test removing ALL withInfo decorators from ALL of your stories and adding it in the root of your storybook config. so that your config might look like this:

import { configure, addDecorator, addParameters} from "@storybook/react";
import { withKnobs } from "@storybook/addon-knobs";
import { withInfo} from "@storybook/addon-info";

function loadStories() {
  const req = require.context("../stories", true, /\.stories\.tsx$/);
  req.keys().forEach(filename => req(filename));
}

addDecorator(
  withInfo({
    inline: true,
  })
);

addParameters({
  backgrounds: [
    { name: "white", value: "#ffffff" },
    { name: "light", value: "#f2f2f2", default: true },
    { name: "dark", value: "#a1a1a1" },
  ],
});

addDecorator(withKnobs);

configure(loadStories, module);

This should add withInfo to all of your stories with inline true. AddParameters are for a seperate react-addon that can change the background color so those aren't relevant.

Finally make sure you are using the latest react and addon-info version.

CheezeCoder avatar Aug 13 '19 12:08 CheezeCoder

Specifying the path to the tsconfig file fixed things for me, thanks!

To wit, my directory structure looks like this:

.storybook/
    addons.js
    config.js
    webpack.config.js
src/
    [...project files...]
package.json
tsconfig.json

The project is using Next.js and doesn't explicitly define its own webpack config, so as recommended by the Storybook docs we just put one in the .storybook directory.

ghost avatar Nov 07 '19 19:11 ghost

Am working on a PR to reinstate this addon into our storybook now in our library and was able to get it working no problems with React.FunctionComponent/React.FC

I am just looking over your earlier configuration and noticed two things.

  1. You should declare addDecorator(withInfo) before (withKnobs) as stated in the git repo.
  2. You should be using React.FC and not StatelessComponent.

I am assuming you've done this already though its impossible to tell without an update example or a link to a repo that I can look at.

Another thing worth mentioning is that if you don't have your webpack.config in the root you might need to tell react-docgen-typescript-loader to find your tsconfig file.

Ex: (if your webpack.config file is one level down from your root, aka ./webpack/webpack.config.js)

{
    loader: require.resolve("react-docgen-typescript-loader"),
    options: {
        tsconfigPath: path.join(__dirname, "../tsconfig.json"),
    },
},

You could also test removing ALL withInfo decorators from ALL of your stories and adding it in the root of your storybook config. so that your config might look like this:

import { configure, addDecorator, addParameters} from "@storybook/react";
import { withKnobs } from "@storybook/addon-knobs";
import { withInfo} from "@storybook/addon-info";

function loadStories() {
  const req = require.context("../stories", true, /\.stories\.tsx$/);
  req.keys().forEach(filename => req(filename));
}

addDecorator(
  withInfo({
    inline: true,
  })
);

addParameters({
  backgrounds: [
    { name: "white", value: "#ffffff" },
    { name: "light", value: "#f2f2f2", default: true },
    { name: "dark", value: "#a1a1a1" },
  ],
});

addDecorator(withKnobs);

configure(loadStories, module);

This should add withInfo to all of your stories with inline true. AddParameters are for a seperate react-addon that can change the background color so those aren't relevant.

Finally make sure you are using the latest react and addon-info version.

It worked for me too, thanks !

ozanmanav avatar Jan 09 '20 09:01 ozanmanav