-
-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
feature request: ability to return a promise from add
#713
Comments
Sounds like an good opportunity! PR is very much welcome! |
this is place where you can start: But I wonder if you need a new functionality why don't consider to create an addon for it instead? Unfortunately, It's missing in the official documentation. I think we will need to update it |
if you can of course, but I doubt you can add support for promises to the core api. it looks like promise support will be needed right here: The story gets added to the But somewhere else the ...and those places ultimately are here: https://github.com/storybooks/react-storybook/blob/master/src/client/preview/render.js#L48 and here: and here it the "preview" rendering is complete: https://github.com/storybooks/react-storybook/blob/master/src/client/preview/index.js#L48 so perhaps just the last 2 calls in the chain need to be made to resolve promises. ...now all that is left is to do it. |
Actually you don't need to touch the final handler passed to export function renderMain(data, storyStore) {
// ...
story(context).next(element => { // THIS NOW RESOLVES A PROMISE!
if (!element) {
const error = {
title: `Expecting a React element from the story: "${selectedStory}" of "${selectedKind}".`,
/* eslint-disable */
description: stripIndents`
Did you forget to return the React element from the story?
Use "() => (<MyComp/>)" or "() => { return <MyComp/>; }" when defining the story.
`,
/* eslint-enable */
};
return renderError(error);
}
if (element.type === undefined) {
const error = {
title: `Expecting a valid React element from the story: "${selectedStory}" of "${selectedKind}".`,
description: stripIndents`
Seems like you are not returning a correct React element from the story.
Could you double check that?
`,
};
return renderError(error);
}
ReactDOM.render(element, rootEl);
return null;
}
}
export default function renderPreview({ reduxStore, storyStore }) {
const state = reduxStore.getState();
if (state.error) {
return renderException(state.error);
}
return Promise.resolve(renderMain(state, storyStore))
.catch(ex => renderException(ex))
}
...@usulpro perhaps you wanna give the decorators a try. The idea is that our story function returns an element, and the decorators can wrap it in a container element. That's all. But the wrapping must be synchronously performed. So they must be resolved as a group. |
the decorators will be more complicated since it happens in a reduce loop. Basically, I think we should pull out the inner most this:
becomes something like this:
note: this assumes decorators don't need the context, but they might. It would actually be a problem if they need the ...now we just need to give it a spin. |
and it turns out, the Storybook team has been planning on removing the |
I imagine the API would look like this: storiesOf('DataViewer')
.add('test', () => fetch('http://api.someURLtogetdata.com').then(r => r.json())
.then(({ data }) => <TestStory data={data} />)
) |
@ndelangen what's the latest on async support? I think we are in agreement in what the API looks like, but I don't suppose you could perhaps go over my guesses on how to implement it above or have someone who knows the codebase do so? I'll likely do it myself in the coming weeks, but it would be helpful to know if I'm on the right rack. |
This might just do it: https://github.com/storybooks/storybook/compare/async-render-support?w=1 Testing it now.. |
Tested, it works great, story re-renders (and promise is re-resolved every time.) Do you want to give this a try @faceyspacey ? |
I made a PR, and will merge it after also adding some documentation and an example in kitchen sink. Want to add your comments @faceyspacey ? |
Wow! I missed this. I'll try to check this out sooner than later. |
Hi @ndelangen, I also need to be able to return a promise from the Am I doing something stupid? |
@dchambers Try this diff maybe? #1253 Hmm, this worked back then.. |
Hi @ndelangen, thanks for the help here and sorry I took so long to come back to you. This diff seems to be an updated but otherwise identical diff to the last one, and the problem I'm seeing is that the Scratch that, I've just realized that this code is only used on the client-side, whereas I've been testing within Jest (using storyshot testing). Although it's not currently working for me in the browser either -- I see this when wrapping my story in a
I have a starting point and will try debugging this further tonight... |
Hi @ndelangen, I've just looked at this again and your diff does work for storybook proper, but it looks like a separate change would be needed to get this working for storyshots. I'm actually only really adding the promise for storyshots because otherwise I can't delay when the snapshots are taken, and this causes them being taken before any data has arrived, so that I just see the loading indicator. I spent a good amount of time trying to get this working on the weekend, but had to work almost blind as a result of the fact that debugging in Jest isn't currently supported with the Node.js inspector (expected to be fixed in 8.4.0) and since Yay, looks like Node.js 8.4.0 has just been released so will try to debug this now... |
I've now been able to get this working for snapshots too. I created an
and then I modified the
As it happens this doesn't actually help me in my case since the asynchronous delay seems to be within the component itself, so that I need some other way to delay the snapshot from being taken to avoid seeing the loading indicator. |
I've now been able to work around my particular issue by using a
Obviously this is probably only useful to me, whereas the |
I was actually able to add the delay I need within the test code, so just regular promise support is working great for me. In case it makes it easier to explain, here's a diff for the changes I'm using: https://github.com/storybooks/storybook/compare/master...dchambers:master?w=1 |
@dchambers I'm glad you are making progress here. Can I ask the reason for the async story in the first place? I've never quite managed to get my head around this particular feature |
@dchambers Awesome progress you're making! |
Hi @tmeasday, in my case I'd like to use to Storyshots to do snapshot testing of GraphQL backed components. Although I connect to an in-process mock GraphQL server rather than a real one for Storybook and unit testing, Apollo still returns the data asynchronously which means that all of my snapshots end up rendering 'Loading...' rather than the components I've created. There may well be other scenarios where the use of promises to delay things might help, but this is the concrete issue I'm facing. I can spend some time tomorrow evening adding some tests and maybe some docs that provide an example that hopefully helps to make sense of this feature. |
@dchambers thanks for the explanation. That makes perfect sense, and I can understand the use case. |
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 60 days. Thanks! |
This feature was never completed, correct? There is no way to asynchronously render a story still? |
Correct 😞 |
My use case is that I'm trying to use Storyshots with a component that, several levels down in its render tree, uses a component that is lazily loaded with |
@pelotom could you |
@tmeasday I tried that (actually just a regular static import at the top of the file) but it didn't seem to work. I think even if the module is immediately available the promise won't resolve synchronously. |
Can you mock `import` to just do nothing?
…On Mon, 16 Apr 2018 at 12:26 pm, Tom Crockett ***@***.***> wrote:
@tmeasday <https://github.com/tmeasday> I tried that (actually just a
regular static import at the top of the file, but it didn't seem to work. I
think even if the module is immediately available the promise won't resolve
synchronously.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#713 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAIFyj89v-rjyjgMUMJ2TQ8Zrs519Zb6ks5tpAFNgaJpZM4MVEe6>
.
|
@tmeasday |
@pelotom this may be getting too complicated, but what about using a different babel plugin for https://www.npmjs.com/package/babel-plugin-dynamic-import-node-sync Could that possibly work? |
@tmeasday I'm not using Babel at all in my project (I'm using TypeScript), and would rather not start now. The solution I'm using for now is to pass down an optional override component to use instead of the lazy one if present. |
Lol, why the thumbs down?? |
I mis-clicked ;) Did you get a notification or something? Looks like a thumbs up for me! |
@tmeasday @dchambers This is still an issue with storybook and snapshot testing. If an extension point of 'beforeSnapshotComparison' was provided in the existing code, everyone could do this. In addition, the code that waits on promises to finish could probably just be inserted no matter what (where fetch-mock is developer specific)
Thoughts? |
@waynebrantley I have struggeling with the excact same issue. All my components follows the same pattern, where all data is loaded in componentDidMount(which I mock using fetch-mock in stories), resulting in empty snapshots since the snapshot is captured before the data is done loading. So your proposal of having an beforeSnapshotComparison extention seems like a great solution for this issue! |
@andwaal if you use the above it will help you do exactly what you want - at the expense of just some copied code. Hopefully, they can just add the extension (with the awaits, etc), but if not - it works great now. |
This comment from #696 offers a simple workaround that worked for me. (sorry for the noise, but this issue is the first result in Google) |
And how to apply |
Imagine you are setting up a redux container component with data from async action creators--well, then you need support for promises and
async/await
in the function passed toadd
.I would like to make a PR. I'm gonna start looking into the code soon. Can you give me some hints where I should apply this. Thanks in advance.
The text was updated successfully, but these errors were encountered: