Skip to content
This repository has been archived by the owner on Nov 20, 2020. It is now read-only.

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

Open
aloifolia opened this issue Nov 15, 2018 · 33 comments
Open

Comments

@aloifolia
Copy link

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

storybookjs/storybook#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 #23. Any idea how to solve it?

@OzairP
Copy link

OzairP commented Nov 17, 2018

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/*"
  ]
}

@aloifolia
Copy link
Author

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)

@stevehanson
Copy link

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 } });

@aloifolia
Copy link
Author

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

@Dudeonyx
Copy link

Dudeonyx commented Nov 26, 2018

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

@teddybradford
Copy link

teddybradford commented Feb 10, 2019

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

@johot
Copy link

johot commented Feb 14, 2019

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
Copy link

johot commented Feb 15, 2019

@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 😄

@strothj
Copy link
Owner

strothj commented Feb 15, 2019

@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
Copy link
Owner

strothj commented Feb 15, 2019

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?

@johot
Copy link

johot commented Feb 18, 2019

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!

@mattdell
Copy link

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;

@draftitchris
Copy link

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.

@ianks
Copy link

ianks commented Apr 11, 2019

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
Copy link

ianks commented Apr 11, 2019

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")
              }
            }
          ]
        }
      ]
    }
  }

@mattdell
Copy link

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

@chrisahardie
Copy link

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>
  )),
);

@dclark27
Copy link

dclark27 commented Apr 12, 2019

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

@draftitchris
Copy link

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 :).

@minya92
Copy link

minya92 commented Jun 14, 2019

For me work this method #33 (comment)

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;
};

@mattdell
Copy link

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?

@draftitchris
Copy link

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

@jdherder
Copy link

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.

@mattdell
Copy link

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
Copy link

mattdell commented Aug 6, 2019

Is no one else using React.FunctionComponent?

@draftitchris
Copy link

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.

@mauriciomelo
Copy link

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

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

@CheezeCoder
Copy link

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.

@ghost
Copy link

ghost commented Nov 7, 2019

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.

@ozanmanav
Copy link

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 !

@clarehuang
Copy link

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 as well, great thanks!

@diondree
Copy link

So is there any reason this loader doesnt work when you're only exporting the component as default?

@piotros
Copy link

piotros commented Apr 22, 2020

I've spent a lot of time looking for a solution why react-docgen-typescript-loader didn't work for me.

I like clean solutions so my components looks like this:

export default function MyComponent(props: MyComponentProps) {
    return <></>;
}

To make react-docgen-typescript-loader work, I had to change this to:

function MyComponent(props: MyComponentProps) {
    return <></>;
}

export default MyComponent;

@strothj can you support my first example?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests