-
-
Notifications
You must be signed in to change notification settings - Fork 9.2k
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
Core: Add async loaders #12699
Core: Add async loaders #12699
Conversation
How would this work if we need to have an async decorator? Something to this regard:
|
@agrohs: you would just refactor things slightly, and add the loader + decorator together: export const loaders = [async () => {
return Promise.resolve({ activeContext: { foo: bar } }),
};
export const decorators = (Story, { loaded: { activeContext } }) => {
return (
<StatefulProvider value={activeContext}>
<Story {...storyContext} />
</StatefulProvider>
)
} Having said that, can you tell us a little bit about your use case? Although this is an escape hatch to support it, we sort of consider async loading of data to be an anti-pattern, so I'm keen to hear about use cases to change my mind on that. |
Thanks @tmeasday, that's exactly what I did and seems to be working as expected now...cheers! |
one minor detail/question is in trying to prevent the loader from running again if its data has already been loaded (or not changed)? Something similar to the following (though it looks like as of now, we don't have access to loaded in the initial payload of the storyContext sent into the loader??)
|
Hmm, I would probably suggest using some external cache here -- I don't know if SB should be doing the caching -- we pass the full context into the loader so for instance the loader could fetch different data depending on the You could do something as simple as using a global var here: let previousContext;
export const loaders = [async ({ loaded: { activeContext: previousContext }}) => {
if (previousContext) {
return previousContext
}
return Promise.resolve({ activeContext: { foo: bar } }).then(v => { previousContext = v; return v });
} |
Is this something that should work on
|
This only works for stories, not |
It seems this does not allow live arg updates to be fed into the loaders, so loaders are not really equivalent to an async Story, as originally proposed in #10009. Edit: Actually args are passed as the first parameter to the loader. |
I don't think the loader will run again if you change the arg using controls. Is that what what you are looking for @Bilge ? |
It does, though. |
Oh, OK then! |
Does data injected from loaders become available to argTypes (in react)? I have a loader that returns data, gets passed to a decorator, then that additional data gets sent to the Story. When I debug the component, the additional top-level prop is available (string array), but it doesn't show as a control. |
Nope they are sort of seperate concepts. You could make an arg that "shadows" the loader and prefer it in the render function for the story? |
If I define the top-level prop for my component as a type property that gets set as an arg.property from the decorator, it shows up as a control (type object). I couldn't find a way to make the string array become a select type control though. |
Issue: #10009
What I did
Asynchronous loaders to provide external data to stories:
unboundStoryFn
to story store, deprecatedstoryFn
How to test
See updated stories in
official-storybook
andhtml-kitchen-sink