Is your feature request related to a problem? Please describe.
I can't load async data to my Storybook without resorting some hacky solution proposed by some other Storybook issues relating to Promise/Async.
Describe the solution you'd like
export const basicForm = async () => {
const { data } = await asyncDataCall()
return <Form data={data} />
}
Will throw Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
or
type PromiseCallback = () => Promise<any>
const withData: PromiseCallback = () => axios('some-endpoint')
addDecorator(withData)
Will also throw an error
Describe alternatives you've considered
Loading using a render prop component https://github.com/storybookjs/storybook/issues/696
Hacky solution using useEffect & useState in this issue. Basically add the promise inside useEffect, and keep a state counter to see if data has been loaded. https://github.com/storybookjs/storybook/pull/1670, but still has issues.
Are you able to assist bring the feature to reality?
not at the moment
Nice writeup. Closing this as dupe to #10009! cc @tmeasday
It's sort of tricky in React because the story function is implicitly a SFC (i.e. a function that returns a React element). They aren't allowed to be async by the rules of React (see error above). We could not render them with React but then React hooks wouldn't work inside stories or decorators.
We discussed the possibility of having a parameter, maybe something like:
export const basicForm = async () => {
const { data } = await asyncDataCall()
return <Form data={data} />
}
basicForm.story = { parameters: { react: { async : true } } }
Where if you passed that parameter you would be allowed to return a promise from the story function, but it would no longer be allowed to use hooks. Any thoughts about that @webberwang?
My use case is for adding dynamically selected decorators. So if ctx.parameters.fileName is ./MONOREPO/packages/viewApp/components/Button, I look for the decorator at ./MONOREPO/packages/viewApp/Storybook.js, with a fallback to a default decorator when the filename doesn't exist.
I don't see a fully dynamic way to do this. The solution I'm going to pursue is importing all existing decorators, then using a map to select from them. Not as pretty, but better than nothing.
I have the exact same scenario - have a decorator who needs to run an async function to get its values and want to pass the values from the response into a component decorator.
Looking for support to be able to do something similar to:
export const getActiveContext = () => {
return Promise.resolve({ foo: bar }); // NOTE: this would call some long running api to bring back data before resolving
}
const withContextProvider = async (Story, storyContext) => {
const activeContext = await getActiveContext(storyContext)
return (
<StatefulProvider value={activeContext}>
<Story {...storyContext} />
</StatefulProvider>
)
}
export const decorators = [
withContextProvider,
]
If I'm following correctly, looks like this should be potentially solved with in: https://github.com/storybookjs/storybook/releases/tag/v6.1.0-alpha.23!?
https://github.com/storybookjs/storybook/issues/10009
https://github.com/storybookjs/storybook/pull/12699
Most helpful comment
If I'm following correctly, looks like this should be potentially solved with in: https://github.com/storybookjs/storybook/releases/tag/v6.1.0-alpha.23!?
https://github.com/storybookjs/storybook/issues/10009
https://github.com/storybookjs/storybook/pull/12699