Skip to content
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

[WIP] (#1736) ability to force re-render a story #2463

Merged
merged 15 commits into from
Dec 28, 2017

Conversation

dangreenisrael
Copy link
Member

@dangreenisrael dangreenisrael commented Dec 11, 2017

Issue: #1736

What I did

added forceReRender to the exports in '@storybook/react'

How to test

Storyshots

Does this need a new example in the kitchen sink apps?

Yes

Does this need an update to the documentation?

Yes

Acceptance criteria:

Platforms

  • React
  • React Native
  • Angular
  • Vue

Functionality

  • Ability to re-render from in stories
  • Ability to re-render from addons via channel

Misc

  • Kitchen sink example (cra)
  • Screenshots

Sceenshot

force rerender

Future possibility

Standard event that can be emitted to force a reload

@codecov
Copy link

codecov bot commented Dec 11, 2017

Codecov Report

Merging #2463 into master will decrease coverage by 0.02%.
The diff coverage is 0%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2463      +/-   ##
==========================================
- Coverage   32.64%   32.61%   -0.03%     
==========================================
  Files         397      397              
  Lines        8847     8855       +8     
  Branches      951      959       +8     
==========================================
  Hits         2888     2888              
+ Misses       5292     5289       -3     
- Partials      667      678      +11
Impacted Files Coverage Δ
app/react/src/client/preview/index.js 0% <0%> (ø) ⬆️
app/angular/src/client/preview/index.js 0% <0%> (ø) ⬆️
app/vue/src/client/preview/index.js 0% <0%> (ø) ⬆️
app/react/src/client/preview/render.js 0% <0%> (ø) ⬆️
app/vue/src/client/preview/render.js 0% <0%> (ø) ⬆️
app/react/src/client/index.js 0% <0%> (ø) ⬆️
app/angular/src/client/preview/render.js 0% <0%> (ø) ⬆️
app/react/src/server/config/babel.js 0% <0%> (-100%) ⬇️
app/react/src/server/utils.js 0% <0%> (-53.58%) ⬇️
lib/ui/src/modules/ui/containers/stories_panel.js 25.71% <0%> (ø) ⬆️
... and 48 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 47dc12e...82699d3. Read the comment docs.

@danielduan
Copy link
Member

Think we should port this over for vue and angular as well if this was to be added as a feature.

@dangreenisrael
Copy link
Member Author

dangreenisrael commented Dec 12, 2017

@danielduan Will do. I'll port it to Vue and Angular when I get a chance, then I'll update the docs for all of them

@@ -53,3 +59,5 @@ const renderUI = () => {
};

reduxStore.subscribe(renderUI);

export const forceReRender = () => renderUI();
Copy link
Member

@ndelangen ndelangen Dec 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the story didn't change, why would this work?

This code:
https://github.com/storybooks/storybook/blob/45f3a7f98e48c1bfeec0d7a2d9210e9701692cc3/app/react/src/client/preview/render.js#L58

Should return true, and the story won't be re-rendered?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, I mis-interpreted the code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just looking at that code, funnily enough and I think it's a bit broken, I was going to send a PR to fix it.

The current (psuedo) logic is:

render() {
  // line linked above
  if (storyDifferent) {
      ReactDOM.unmountComponentAtNode(rootEl);
  }

  // later
  ReactDOM.render(element, rootEl);
}

So it always calls render and sometimes calls unmount. This actually breaks the React lifecycle in weird ways.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if I was to fix the above (probably changing it to: if (!storyDifferent) return;, this PR would no longer work.

We should consider if we want to support this forceRerender functionality? I suppose we do? If so we will need a more declarative way to make it work, I don't think we should retain the above bug just to make it work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably the easiest way would be to add a "key" to the redux store that is changed when you call forceRerender and to also check if the key has changed.

window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__({ name: 'Storybook Preview', instanceId: 'sbPreview' })
);
/* eslint-enable */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's happening with this change? It seems unrelated.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, it is unrelated. It's enabling dev tools. Do you think it should be in a separate branch/pr.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yeah, let's move to a separate PR

@@ -53,3 +59,5 @@ const renderUI = () => {
};

reduxStore.subscribe(renderUI);

export const forceReRender = () => renderUI();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just looking at that code, funnily enough and I think it's a bit broken, I was going to send a PR to fix it.

The current (psuedo) logic is:

render() {
  // line linked above
  if (storyDifferent) {
      ReactDOM.unmountComponentAtNode(rootEl);
  }

  // later
  ReactDOM.render(element, rootEl);
}

So it always calls render and sometimes calls unmount. This actually breaks the React lifecycle in weird ways.

@@ -53,3 +59,5 @@ const renderUI = () => {
};

reduxStore.subscribe(renderUI);

export const forceReRender = () => renderUI();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if I was to fix the above (probably changing it to: if (!storyDifferent) return;, this PR would no longer work.

We should consider if we want to support this forceRerender functionality? I suppose we do? If so we will need a more declarative way to make it work, I don't think we should retain the above bug just to make it work.

@tmeasday
Copy link
Member

@dangreenisrael I am making some of these changes on another branch (because I need the lifecycle to work properly) so LMK if it makes sense to port them across here.

@tmeasday
Copy link
Member

PS as an aside -- is it expected that all new functionality needs to be implemented in all 3 (should it be 4, what about RN?) view layers to be shipped? For instance, I personally wouldn't have much idea how to (at least idiomatically) implement this in Vue and Angular. It seems like quite a barrier (maybe that's a good thing).

@dangreenisrael
Copy link
Member Author

@tmeasday I'm planning to do a deep dive into force re-render over the winter holidays (probably December 27,28,29. Do you think your PR will be merged by then.

@dangreenisrael
Copy link
Member Author

@tmeasday @ndelangen Do you guys want to set up a time to chat about force re-render so we can all get on the same page

@tmeasday
Copy link
Member

@dangreenisrael - #2503

I'm pretty convinced we should merge the above. However, I think it shouldn't be too hard to amend the above to consider a renderKey or something from the redux store.

@dangreenisrael
Copy link
Member Author

@tmeasday, I'll rebase off 3.3/your branch before getting back to work on this

@ndelangen
Copy link
Member

Please check if this still works after @tmeasday's change..

@Hypnosphi Hypnosphi changed the base branch from release/3.3 to master December 23, 2017 23:56
@tmeasday
Copy link
Member

Changes look good to me.

Copy link
Member

@tmeasday tmeasday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, let's get rid of the devtools

window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__({ name: 'Storybook Preview', instanceId: 'sbPreview' })
);
/* eslint-enable */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yeah, let's move to a separate PR

@Hypnosphi Hypnosphi added this to the v3.4.0 milestone Dec 27, 2017
@ndelangen
Copy link
Member

merge conflicts

…#1736)-Ability-to-force-redender-a-story

# Conflicts:
#	app/react/src/client/preview/render.js
@dangreenisrael dangreenisrael dismissed tmeasday’s stale review December 28, 2017 18:38

I addressed the concerns, but his is unable to look at it right now.

@dangreenisrael dangreenisrael merged commit 4b5622a into master Dec 28, 2017
@dangreenisrael dangreenisrael deleted the (#1736)-Ability-to-force-redender-a-story branch December 28, 2017 18:39
@dangreenisrael
Copy link
Member Author

Merging as @tmeasday's requested changes were made

@stefanKuijers
Copy link

Thank you guys for the great work. As far as I can see this has been merged in and master. I'm using version 3.3.12 but cannot run the example code.

@dangreenisrael: Sadly when using the example code I run into the following error
When I call forceReRender I get the following error:

    at increment (0.345baf011dfa0388ca2e.hot-update.js:70)
    at HTMLUnknownElement.callCallback (preview.bundle.js:30287)
    at Object.invokeGuardedCallbackDev (preview.bundle.js:30326)
    at Object.invokeGuardedCallback (preview.bundle.js:30183)
    at Object.invokeGuardedCallbackAndCatchFirstError (preview.bundle.js:30197)
    at executeDispatch (preview.bundle.js:30581)
    at executeDispatchesInOrder (preview.bundle.js:30603)
    at executeDispatchesAndRelease (preview.bundle.js:30701)
    at executeDispatchesAndReleaseTopLevel (preview.bundle.js:30712)
    at Array.forEach (<anonymous>)

It is thrown two times: 0.345baf011dfa0388ca2e.hot-update.js:70 & @ preview.bundle.js:30355.

When I look into the cra-kitchensink folder I don't see anything special in the setup which differs from mine. Is there still a change this is related to setup? For example that I'm using different loaders? (TS, SCSS)

Thanks in advance!

@dangreenisrael
Copy link
Member Author

@stefanKuijers could you open up an issue for this? Also, can you reproduce this issue in a public repo?

@Hypnosphi
Copy link
Member

Hypnosphi commented Feb 8, 2018

@stefanKuijers This feature was merged after 3.3.0 release, so it targets 3.4.0 (currently in alpha, 3.4.0-alpha.7)

@stefanKuijers
Copy link

Thanks for the reply guys. I saw a few times in the branch names a 3.3 which is why I thought it was still part of 3.3.

Thanks for the great work! I will wait until 3.4.0. I see on the side now that this is assigned to the 3.4 milestone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants