Does Storybook have an opinion or mechanism for providing state to controlled components? #21680
Replies: 6 comments 8 replies
-
Hi @dwjohnston sorry we could not answer your interesting question we were busy with the V7 RC. So the answer for me is you newWayAttempt2 seems just perfect. |
Beta Was this translation helpful? Give feedback.
-
yes storybook control can't be function as it will be issue with code injection which is not safe, however args can be functions that return a values type string , number , json , string[] ,number[] ... |
Beta Was this translation helpful? Give feedback.
-
Would it make sense to treat args as state? I mean essentially args are state, you can edit it directly and it update the component right away. My use case is for a RadioGroup. If we could use the onChange handler to modify the args then it wouldn't require the addition of state. I know it works fine adding state but the automated documentation ends up being different than it should be used since you have to add an intermediate component that holds the state. I'm sure it's not trivial to add something like this but wondering if it even makes sense based on the Storybook paradigm. |
Beta Was this translation helpful? Give feedback.
-
You can add custom action if you add import { action } from '@storybook/addon-actions'
...
const onChange = (value) => {
action('onChange')(value) // or action('onChange: ' + value)()
setValue(value)
} Unfortunately, it is undocumented AFAIK. I find it is very confusing that we have |
Beta Was this translation helpful? Give feedback.
-
I think I fixed all the problems and could connect controlled component to Controls. See here: https://stackblitz.com/edit/github-uixpen-p6osgl?file=src%2Fstories%2FInputField.js,src%2Fstories%2FInputField.stories.js To make code cleaner I added const useControlledProps = (args) => {
const [, setArgs] = useArgs()
const [value, setValue] = useState(args.value || null)
useEffect(() => {
action('onChange')(args.value)
setValue(args.value)
}, [args.value])
const onChange = (value) => {
action('onChange')(value)
setArgs({ value: value })
setValue(value)
}
return ({
value: value,
onChange: onChange,
})
} and use in component's template: const Template = {
render: function Render(args) {
const { value, onChange } = useControlledProps(args)
return <>
<InputField
{...args}
value={value}
onChange={onChange}
/>
<button onClick={() => {onChange('ddd')}}>set "ddd" value</button>
</>
},
}```
For functional components it works good. |
Beta Was this translation helpful? Give feedback.
-
my preference for wrapping controlled components with stateful components (in React) is Decorators. you could pair this with Actions to spy on the event-handling interfaces. this would allow you to avoid building an ad-hoc logger inside the canvas. we use play functions to put stories into specific states — using testing-library events. |
Beta Was this translation helpful? Give feedback.
-
Introduction
In my current code base, I commonly write stories like this:
That is, I have a controlled component. I want to test the behaviour of this component, allow the viewer to see how it behaves as you select new items.
To do this, I declare state in the storybook component.
What's in the docs?
There is the Actions essential plug in, which can detect click events etc. This appears to be good for detecting standard 'onClick' or 'onSubmit' type payloads, but doesn't appear to have a mechanism for setting some state.
The controls don't appear to have a function type arg, and in anycase, the use case I've got here actually pairs two of the args (onChange and selectedValue) together.
My investigation
I have done a bit of an investigation here.
We can also write a story like this:
This works absolutely fine.
What I'm wondering here, is am I missing a feature, or does Storybook otherwise have an opinion on how we would demonstrate this behaviour?
Beta Was this translation helpful? Give feedback.
All reactions