storybook: ForwardRef source code problem when using Args

Describe the bug When using Args my story source code seems to be some kind of stringify source code instead of the actual JSX code.

To Reproduce

<Canvas>
    <Story name="icon">
        {args =>
            <Button {...args}>
                <LightbulbIcon />
                <Text>Cutoff</Text>
            </Button>
        }
    </Story>
</Canvas>

Expected behavior JSX soure code well indented 😃

Screenshots With Args:

image

Without Args:

image

Code snippets If applicable, add code samples to help explain your problem.

System Please paste the results of npx sb@next info here.

Additional context Add any other context about the problem here.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (14 by maintainers)

Most upvoted comments

The above comment from @andezzat really helped me, thanks! However, if it helps anyone coming from Google there was a subtle distinction that was needed for my case:

Storybook version: 6.4.20

I was already destructuring forwardRef upon import (as many people in various Github issues have suggested), explicitly setting the types upon invoking forwardRef<A, B>(), and ensuring my component function was set to a const:

import React, { forwardRef, ForwardedRef } from 'react';

export type CodeFieldInputProps = {
 ...
};

const CodeFieldInput = (
  props: CodeFieldInputProps,
  ref: ForwardedRef<HTMLInputElement>
) => (
  <input
    ...
    ref={ref}
  />
);

export default forwardRef<HTMLInputElement, CodeFieldInputProps>(CodeFieldInput);

However the key appears to be that you need to do the invocation of forwardRef within the const and not upon export default, like I did above. Here’s the working code:

import React, { forwardRef, ForwardedRef } from 'react';

export type CodeFieldInputProps = {
 ...
};

const CodeFieldInput = forwardRef<HTMLInputElement, CodeFieldInputProps>(
  (
    props: CodeFieldInputProps,
    ref: ForwardedRef<HTMLInputElement>
  ) => (
    <input
      ...
      ref={ref}
    />
  )
);

export default CodeFieldInput;

Hope this saves someone some time 😃

It does fix the issues indeed 😃

Howhever I had to specify manually a displayName instead since you can’t that kind of exports export { Button: slot("button", Button) };

Thank you @andezzat

Oh sorry for the build error, still WIP hehe.

I’ll give it a shot tomorrow, thank you very much for your help @andezzat

@patricklafrance Thank you!

I tried cloning & installing but was met with a build error on yarn build:pkg

lerna ERR! yarn run build stderr:
(node:9472) [DEP0148] DeprecationWarning: Use of deprecated folder mapping "./" in the "exports" field module resolution of the package at C:\Users\Andrew\Sites\sg-orbit\node_modules\cssstats\node_modules\postcss\package.json.
Update this package.json to use a subpath pattern like "./*".
(Use `node --trace-deprecation ...` to show where the warning was created)
Error: Failed to find '../../foundation/dist/apricot.css'
  in [
    C:\Users\Andrew\Sites\sg-orbit\packages\tachyons\src
  ]
    at C:\Users\Andrew\Sites\sg-orbit\node_modules\postcss-import\lib\resolve-id.js:35:13
lerna ERR! yarn run build stderr:
(node:9472) [DEP0148] DeprecationWarning: Use of deprecated folder mapping "./" in the "exports" field module resolution of the package at C:\Users\Andrew\Sites\sg-orbit\node_modules\cssstats\node_modules\postcss\package.json.
Update this package.json to use a subpath pattern like "./*".
(Use `node --trace-deprecation ...` to show where the warning was created)
Error: Failed to find '../../foundation/dist/apricot.css'
  in [
    C:\Users\Andrew\Sites\sg-orbit\packages\tachyons\src
  ]
    at C:\Users\Andrew\Sites\sg-orbit\node_modules\postcss-import\lib\resolve-id.js:35:13

Regardless, I think I know what’s going wrong 😄

export const Button = slot("button", forwardRef((props, ref) => (
    <InnerButton {...props} forwardedRef={ref} />
)));

The current way the Button is exported for eg., doesn’t actually assign a displayName to the forwardRef component, so SB can’t find its name. In order to fix this, try assigning the forwardRef component to a const first.

This may work?

// This assignment will do `Button.displayName = 'Button'`
const Button = forwardRef((props, ref) => (
    <InnerButton {...props} forwardedRef={ref} />
));

export { Button: slot("button", Button) };

@andezzat here’s a live example: https://5fc11202b9a514946ac633fe--sg-storybook.netlify.app/?path=/docs/button--test#test

My repository is public if you want to try it: https://github.com/gsoft-inc/sg-orbit/tree/storybook-6

To install & start Storybook

  • git clone https://github.com/gsoft-inc/sg-orbit.git
  • git checkout storybook-6
  • yarn bootstrap (DO NOT do a yarn install)
  • yarn build:pkg
  • yarn start-sb

Hope this help.

Thank you

@andezzat It’s a default SB setup without TS. My stories are defined using MDX.

What is confusing? Isn’t it Canvas the replacement for Preview in 6? The render function is to support Args in thestory.

How would you do it? I might use the wrong syntax.

@andezzat mind taking a look at this?

@patricklafrance As a workaround, you can set the docs.source.type parameter to “code”