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

Using knobs in global decorators #31

Closed
firebait opened this issue Sep 17, 2016 · 5 comments
Closed

Using knobs in global decorators #31

firebait opened this issue Sep 17, 2016 · 5 comments

Comments

@firebait
Copy link

This is more like a question but I have a use case in which I would like to use knobs at the global decorator level, so I added the following code to my config.js like this:

addDecorator((story) => (
  <ThemeProvider theme={select('Theme', themes, 'Light')}>
    {story()}
  </ThemeProvider>
));

The above code fails on this error becuase I think because the knob store is not been created yet:

Cannot read property 'get' of null
TypeError: Cannot read property 'get' of null
    at KnobManager.knob (webpack:///~/@kadira/storybook-addon-knobs/dist/KnobManager.js:50:35)
    at select (webpack:///~/@kadira/storybook-addon-knobs/dist/index.js:47:18)
    at eval (webpack:///:21:46)
    at eval (webpack:///~/@kadira/storybook/dist/client/preview/client_api.js:95:20)
    at renderMain (webpack:///~/@kadira/storybook/dist/client/preview/render.js:85:31)
    at renderPreview (webpack:///~/@kadira/storybook/dist/client/preview/render.js:101:10)
    at Array.renderUI (webpack:///~/@kadira/storybook/dist/client/preview/index.js:89:26)
    at Object.dispatch (webpack:///~/redux/lib/createStore.js:186:19)
    at ConfigApi._renderMain (webpack:///~/@kadira/storybook/dist/client/preview/config_api.js:48:24)
    at render (webpack:///~/@kadira/storybook/dist/client/preview/config_api.js:66:17)
@roonyh
Copy link
Contributor

roonyh commented Sep 17, 2016

Yeah, the knob store is not created because story here is not decorated with the withKnobs decorator yet. Its a little tricky but following should work.

import { withKnobs, select } from '@kadira/storybook-addon-knobs';

addDecorator((story, context) => {
    const storyWithKnobs = withKnobs(story, context) // explicitly add withKnobs

    return (
      <ThemeProvider theme={select('Theme', ['Light', 'Dark'], 'Light')}>
        {storyWithKnobs}
      </ThemeProvider >
    );
  }
);

This explicitly adds withKnobs decorator to the story before adding your own decorator. This makes it behave like you globally decorated with withKnobs too. So you can remove other addDecorator(withKnobs) calls from your stories.

@roonyh
Copy link
Contributor

roonyh commented Sep 17, 2016

Or this way which looks slightly cleaner.

addDecorator(withKnobs) // add withKnobs
addDecorator((story) => {

    const content = story() // call story early so knob store is created before `select` call

    return (
      <ThemeProvider theme={select('Theme', themes, 'Light')}>
        {content}
      </ThemeProvider >
    );
  }
);

@firebait
Copy link
Author

firebait commented Sep 18, 2016

HI @roonyh, thanks!. This works on rendering the knob correctly but for some reason when I switch the theme it does not trigger a prop change. I'll try to dig to see if my code is missing something.

Btw, the url does change, I just think there is no render being triggered as when I refresh the page the new selected value is applied.

@firebait
Copy link
Author

Confirmed, I can switch the theme using the react dev tools but not with the knobs, it might be because it's out of context?

@firebait
Copy link
Author

After further research I found that it does call forceUpdate but on the WrapStory component but the decorator is outside this scope so it does not get updated. So proper way to implement this was to add the decorator and then add knobs like so:

addDecorator((story) => {

    const content = story() // call story early so knob store is created before `select` call

    return (
      <ThemeProvider theme={select('Theme', themes, 'Light')}>
        {content}
      </ThemeProvider >
    );
  }
);
addDecorator(withKnobs) // add withKnobs

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

No branches or pull requests

2 participants