Describe the bug
Hard to describe, but the knobs are not working unless the options are directly defined in the props of the story. I normally define a props variable I can share between stories for common data. If I put any knob options in this props variable it will not display in the knobs tab in Storybook. Occasionally if I refresh the page I can see both select knobs, but if I change the width one it will just disappear completely. The widthThatWorks has no issue and does update in Storybook properly.
To Reproduce
Run the story file code below.
Expected behavior
The code below should display two select knob options. Occasionally displays both, but only one ever works.
Screenshots
Here's how it looks when they both finally display.

What it looks like if you make a change to width.

Code snippets
import { select, withKnobs } from '@storybook/addon-knobs';
import { moduleMetadata, storiesOf } from '@storybook/angular';
const props = {
width: select('width', ['full', 'auto', 200, 320, 400, 600], 320)
};
storiesOf('Knob Test', module)
.addDecorator(
moduleMetadata({
imports: []
})
)
.addDecorator(withKnobs)
.add('Basic', () => ({
template: `
width: {{ width }}<br>
widthThatWorks: {{ widthThatWorks }}
`,
props: {
...props,
widthThatWorks: select('widthThatWorks', ['full', 'auto', 200, 320, 400, 600], 320)
}
}));
System:
@chriscarpenter12 While we wait for this to be fixed, you can change your props to be inline functions.
const props = {
width: () => select('width', ['full', 'auto', 200, 320, 400, 600], 320)
};
And then just invoke the function like width():
storiesOf('Knob Test', module)
.addDecorator(
moduleMetadata({
imports: []
})
)
.addDecorator(withKnobs)
.add('Basic', () => ({
template: `
width: {{ width() }}<br>
`,
props: {
...props,
}
}));
I know it's annoying, but it works.
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!
@smesko85 It seems that with this implementation it is flooding the console of Firefox and IE with hundreds of messages like:
message arrived at manager storybookjs/knobs/set
Object { knobs: {鈥, timestamp: 1564666731046 }
Doesn't seem to happen in Chrome.
Moving the knobs back inline to each story fixes this. After a while it basically crashes the browser from so much logging.
@chriscarpenter12 Sorry to hear that. I've been using this approach in React project without issue :(
Not entirely sure what's going on here because I don't use Angular. But:
1) I believe this is related to the number of messages coming through: https://github.com/storybookjs/storybook/commit/e651a3bdbc14834943a7362508ae5840f849752c
2) These messages only show up when you have log level verbose enabled. Maybe a workaround is to turn that off?
My npm script to start it set to run the below command. I'm not setting verbose anywhere. Like I said it's only output in Firefox and IE not Chrome.
start-storybook -p 5000 --ci -s ../style
@chriscarpenter12 that's a browser setting AFAIK. at least it is in chrome devtools
This method of setting a prop with an arrow function to call the knob is causing Angular's change detection lifecycle to constantly run. I was debugging a component and noticed change detection was constantly firing. Bringing the knobs back inline with the story prop resolved this too. Do we know what the actual issue is with defining props in an object outside the story?
This is also an issue when working with React:
const slotPickerData = {
nextCollectionSlot: select('nextCollectionSlot', {
None: null,
Slot: { id: '1234', startsAt: '18:00', endsAt: '19:00', date: '2019-09-05' }
})
};
componentStories.add('QuickSlotPicker', () => (
<QuickSlotPicker {...slotPickerData} />
));
The above will display knobs in Storybook's UI, but when attempting to change them nothing will happen, unless props that use knobs are declared directly on the component in such a way:
componentStories.add('QuickSlotPicker', () => (
<QuickSlotPicker
{...{
nextCollectionSlot: select('nextCollectionSlot', {
None: null,
Slot: { id: '1234', startsAt: '18:00', endsAt: '19:00', date: '2019-09-05' }
})}
/>
));
@matthewmorek The solution that @smesko85 suggested does work it just causes some side effects for me in Angular.
const slotPickerData = {
nextCollectionSlot: () => select('nextCollectionSlot', {
None: null,
Slot: { id: '1234', startsAt: '18:00', endsAt: '19:00', date: '2019-09-05' }
})
};
Then call nextCollectionSlot() in your template to return the select knob.
True, it does work, but I would not advise using it because:
I have deferred to implementing knobs using duplicate data sets until this issue is resolved, in which case all code bloat will go away organically. Not ideal, but to me it seems it has less downsides that way.
Since this issue isn't just impacting Angular apps (React is affected too, as per above), I'd like to request to drop Angular from the issue title, to make sure it has universally better visibility. Some people may overlook it, thinking it doesn't apply when used with frameworks other than Angular.
@matthewmorek Updated the title.
TBH, knobs is legacy code at this point and in need of a major cleanup. We're hoping to rearchitect it for 6.0 to address these issues and more.
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!
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!
馃憢 This is late to the convo since Storybook V6 is already out 馃檲 but for those that are still facing this issue I found a workaround that is not too bad 馃槢
When defining your props, create a function similar to the one below
const componentProps = () => ({
name: text("name", "Bob"),
isAvailable: boolean("isAvailable", false),
// You get the drift!
})
Then spread the function as your would with object props and call the function. _Note that this is using the new Component Story Format (CSF)._
export function isNotAvaiable() {
return <Component {...componentProps()}/>
}
TLDR 馃
export function isNotAvaiable() {
return <Component {...componentProps()}/>
}
const componentProps = () => ({
name: text("name", "Bob"),
isAvailable: boolean("isAvailable", false),
// You get the drift!
})
@KoltonG Should we use your method for Storybook React Native (Since React Native is still on V5.3 and hasn't been migrated to V6 yet?
馃憢 This is late to the convo since Storybook V6 is already out 馃檲 but for those that are still facing this issue I found a workaround that is not too bad 馃槢
When defining your props, create a function similar to the one below
const componentProps = () => ({ name: text("name", "Bob"), isAvailable: boolean("isAvailable", false), // You get the drift! })Then spread the function as your would with object props and call the function. _Note that this is using the new Component Story Format (CSF)._
export function isNotAvaiable() { return <Component {...componentProps()}/> }TLDR 馃
export function isNotAvaiable() { return <Component {...componentProps()}/> } const componentProps = () => ({ name: text("name", "Bob"), isAvailable: boolean("isAvailable", false), // You get the drift! })
Just tried this can confirm it works but keep in mind it will re-render the component every time you
1) Click Navigator or Addons
2) Update a Knob.
On the bright side, it doesn't continuously re-render infinitely, meaning if you do no action the component won't re-render!
@KoltonG, I've been using this pattern but it doesn't seem to work for the select knob. From what I'm observing, that one still has to be defined as a prop to the component. Can you confirm on your end if that's the case? Trying to figure out if it's just a problem on my end.
@nunoleong
import React from "react";
import { storiesOf } from "@storybook/react-native";
import { CardColorSquare, ICardColorSquare } from "./index";
import { select, text } from "@storybook/addon-knobs";
type TCardColorSquareArgs = (
color?: string,
groupID?: string,
) => ICardColorSquare;
export const CardColorSquareArgs: TCardColorSquareArgs = (
color = 'pink',
groupID= 'CardColorSquareArgs'
) => {
return {
color: select('color',['blue','red'], 'red', groupID),
}
}
storiesOf("CardColorSquare", module).add("Basic", () => (
<CardColorSquare {...CardColorSquareArgs()} />
));
Works fine for me!
Most helpful comment
@matthewmorek Updated the title.
TBH, knobs is legacy code at this point and in need of a major cleanup. We're hoping to rearchitect it for 6.0 to address these issues and more.