Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

addon-docs MDX: State management #9602

Closed
zslabs opened this issue Jan 22, 2020 · 12 comments
Closed

addon-docs MDX: State management #9602

zslabs opened this issue Jan 22, 2020 · 12 comments

Comments

@zslabs
Copy link

zslabs commented Jan 22, 2020

I may have overlooked this since the docs are still being worked on for MDX, but what's the way to manage state in my stories using MDX? Right, now, I'm importing a component that handles the state management in a normal .js file, but then the code examples are a bit lackluster in the <Preview /> window:

<Preview>
  <Story name="Default">
    <Default />
  </Story>
</Preview>
@shilman
Copy link
Member

shilman commented Jan 23, 2020

You can use hooks in MDX stories:

https://github.com/storybookjs/storybook/blob/master/examples/official-storybook/stories/demo/button.stories.mdx#L30

@zslabs
Copy link
Author

zslabs commented Jan 23, 2020

@shilman Ah, thank you very much - super useful! Have a great day!

@zslabs zslabs closed this as completed Jan 23, 2020
@zslabs
Copy link
Author

zslabs commented Jan 23, 2020

@shilman I noticed a few funny things when attempting to get this to work, and wasn't sure if it may merit another issue being opened for each.

Spacing between code lines isn't allowed:

<Preview>
  <Story name="Default">
    {() => {
      const [value, setValue] = useState(2)

      return (
        <Range
          label="Range"
          name="example"
          value={value}
          step={1}
          min={1}
          max={20}
          disabled={boolean('Disabled', false)}
          onChange={({ target: { value: rangeValue } }) => {
            action('Current value')(rangeValue)

            setValue(rangeValue)
          }}
        />
      )
    }}
  </Story>
</Preview>

Notice the blank lines after the state declaration and in the onChange handler. With them there, I get the following:

Module build failed (from ./node_modules/@mdx-js/loader/index.js):
SyntaxError: unknown: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>? (34:9)

  32 |   )
  33 | }}
> 34 | `}</code></pre>
     |          ^
  35 |   </Story>
  36 | </Preview>

When I remove those blank-lines, all is well.

Emotion css prop is busted

This works inside of normal CSF, but in MDX; I get the following:

You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop).

I tried the workaround mentioned in #6853 (comment) which unfortunately didn't work, so at first-thought it'd seem like a deficiency in MDX.

I'll re-open this ticket, but definitely understand if this should be broken out; just let me know. Thanks!

@zslabs zslabs reopened this Jan 23, 2020
@shilman
Copy link
Member

shilman commented Jan 23, 2020

thanks @zslabs! both have issues: #7902 #7540

@shilman shilman closed this as completed Jan 23, 2020
@ZhihaoLau
Copy link

ZhihaoLau commented Feb 1, 2020

You can use hooks in MDX stories:

https://github.com/storybookjs/storybook/blob/master/examples/official-storybook/stories/demo/button.stories.mdx#L30

Somehow I come across a problem in this way, the setCount or whatever React.SetStateAction will trigger a whole new render.
which become an issue to some complex components depend on lifecycle methods.
Sample:

{() => {
      const [count, setCount] = useState("1");
      const Wrap = styled.div`
        height: 200px;
        width: 100%;
        background-color: #eee;
        padding: 15px;
        box-sizing: border-box;
      `;
      return (
        <Wrap>
          <MyTabs defaultActiveKey={count} onChange={setCount} />
        </Wrap>
      );
    }}

when I trigger onChange, the MyTabs component will destroy & re-contruct all again.

when I try to implement it on codesandbox , Eslint yields "React Hook "useState" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function. (react-hooks/rules-of-hooks)eslint"
codesandbox, but it works, not triggering a whole new construct.

In other words: seems setCount or other SetStateAction triggers the <Story>{() => {}}</Story> execute again

@shilman shilman reopened this Feb 2, 2020
@sami616
Copy link

sami616 commented Feb 18, 2020

Does using a function as a child only work directly under a <Story/> component? I'm trying to achieve the same thing but i only need a <Preview/> (i'm using mdx purely for docs)

@shilman
Copy link
Member

shilman commented Feb 18, 2020

@sami616 yeah i think there's some special magic for that in the Story block

@sami616
Copy link

sami616 commented Feb 18, 2020

Thanks for the reply, worth adding a feature request? i cant imagine i'm the only person that would benefit from this.

@sami616
Copy link

sami616 commented Feb 18, 2020

For anyone who comes across this, you can write a little utility component which handles this:

type FunctionProps = {
  children: () => React.ReactNode
}

export const Function = ({ children }: FunctionProps) => children()

@stale
Copy link

stale bot commented Mar 11, 2020

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

@stale
Copy link

stale bot commented Apr 10, 2020

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

@stale stale bot closed this as completed Apr 10, 2020
@grelas
Copy link

grelas commented Jun 23, 2022

You can use hooks in MDX stories:

https://github.com/storybookjs/storybook/blob/master/examples/official-storybook/stories/demo/button.stories.mdx#L30

this worked nicely! one thing I'm running into when trying to follow this example is the formatting (see screenshot)
image

im on v6.5.9 of storybook, and have the following in preview.js:

docs: {
  transformSource: (input) =>
    prettier.format(input, {
      parser: 'mdx',
      plugins: [parserMarkdown, parserBabel]
    })
},

from issue #8078 (comment)

any idea on how to fix this formatting when using the example you provided? (e.g. the indentation)

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

No branches or pull requests

5 participants