From 98fa5cd11769cb03950649cea918cb62c6ff0d2f Mon Sep 17 00:00:00 2001 From: Dan Green Date: Mon, 11 Dec 2017 17:52:28 -0500 Subject: [PATCH 1/5] (#1736) Adds Ability to re-render a story programatically in react Also adds support for redux DevTools in react/client --- app/react/src/client/index.js | 9 ++++++++- app/react/src/client/preview/index.js | 10 +++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/react/src/client/index.js b/app/react/src/client/index.js index da10136436bc..889ca11bfa29 100644 --- a/app/react/src/client/index.js +++ b/app/react/src/client/index.js @@ -4,7 +4,14 @@ import deprecate from 'util-deprecate'; import { action as deprecatedAction } from '@storybook/addon-actions'; import { linkTo as deprecatedLinkTo } from '@storybook/addon-links'; -export { storiesOf, setAddon, addDecorator, configure, getStorybook } from './preview'; +export { + storiesOf, + setAddon, + addDecorator, + configure, + getStorybook, + forceReRender, +} from './preview'; export const action = deprecate( deprecatedAction, diff --git a/app/react/src/client/preview/index.js b/app/react/src/client/preview/index.js index 60508441eeee..8aa17f744e8c 100644 --- a/app/react/src/client/preview/index.js +++ b/app/react/src/client/preview/index.js @@ -20,7 +20,13 @@ const isBrowser = !(navigator.userAgent.indexOf('Node.js') > -1); const storyStore = new StoryStore(); -const reduxStore = createStore(reducer); +/* eslint-disable no-underscore-dangle */ +const reduxStore = createStore( + reducer, + window.__REDUX_DEVTOOLS_EXTENSION__ && + window.__REDUX_DEVTOOLS_EXTENSION__({ name: 'Storybook Preview', instanceId: 'sbPreview' }) +); +/* eslint-enable */ const context = { storyStore, reduxStore }; if (isBrowser) { @@ -53,3 +59,5 @@ const renderUI = () => { }; reduxStore.subscribe(renderUI); + +export const forceReRender = () => renderUI(); From 45f3a7f98e48c1bfeec0d7a2d9210e9701692cc3 Mon Sep 17 00:00:00 2001 From: Dan Green Date: Mon, 11 Dec 2017 18:46:55 -0500 Subject: [PATCH 2/5] (#1736) Add cra example for force re-render --- .../src/stories/force-rerender.stories.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 examples/cra-kitchen-sink/src/stories/force-rerender.stories.js diff --git a/examples/cra-kitchen-sink/src/stories/force-rerender.stories.js b/examples/cra-kitchen-sink/src/stories/force-rerender.stories.js new file mode 100644 index 000000000000..92b83adfdcc3 --- /dev/null +++ b/examples/cra-kitchen-sink/src/stories/force-rerender.stories.js @@ -0,0 +1,12 @@ +import React from 'react'; +import { storiesOf, forceReRender } from '@storybook/react'; + +let count = 0; +const increment = () => { + count += 1; + forceReRender(); +}; + +storiesOf('Force ReRender', module).add('button', () => ( + +)); From d4609e449e6644fd23e18c83416edd0a712ab9bb Mon Sep 17 00:00:00 2001 From: Dan Green Date: Tue, 26 Dec 2017 21:57:28 -0500 Subject: [PATCH 3/5] (#1736) Update forceReRender to not rely on a bug --- app/react/src/client/preview/index.js | 2 +- app/react/src/client/preview/render.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/react/src/client/preview/index.js b/app/react/src/client/preview/index.js index 8aa17f744e8c..bb7723c1aa89 100644 --- a/app/react/src/client/preview/index.js +++ b/app/react/src/client/preview/index.js @@ -60,4 +60,4 @@ const renderUI = () => { reduxStore.subscribe(renderUI); -export const forceReRender = () => renderUI(); +export const forceReRender = () => render(context, true); diff --git a/app/react/src/client/preview/render.js b/app/react/src/client/preview/render.js index 1e16b7b10685..7f7a9e8ba1d1 100644 --- a/app/react/src/client/preview/render.js +++ b/app/react/src/client/preview/render.js @@ -38,7 +38,7 @@ export function renderException(error) { logger.error(error.stack); } -export function renderMain(data, storyStore) { +export function renderMain(data, storyStore, forceRender) { if (storyStore.size() === 0) return null; const NoPreview = () =>

No Preview Available!

; @@ -55,7 +55,7 @@ export function renderMain(data, storyStore) { // renderMain() gets executed after each action. Actions will cause the whole // story to re-render without this check. // https://github.com/storybooks/react-storybook/issues/116 - if (selectedKind === previousKind && previousStory === selectedStory) { + if (!forceRender && selectedKind === previousKind && previousStory === selectedStory) { return null; } @@ -100,14 +100,14 @@ export function renderMain(data, storyStore) { return null; } -export default function renderPreview({ reduxStore, storyStore }) { +export default function renderPreview({ reduxStore, storyStore }, forceRender = false) { const state = reduxStore.getState(); if (state.error) { return renderException(state.error); } try { - return renderMain(state, storyStore); + return renderMain(state, storyStore, forceRender); } catch (ex) { return renderException(ex); } From 597387c8389dc631d97a724524b8f860f0830cca Mon Sep 17 00:00:00 2001 From: Dan Green Date: Wed, 27 Dec 2017 10:28:53 -0500 Subject: [PATCH 4/5] (#1736) Add forceReRender support for Angular and Vue --- app/angular/src/client/preview/index.js | 2 ++ app/angular/src/client/preview/render.js | 8 ++++---- app/react/src/client/preview/index.js | 6 +----- app/vue/src/client/preview/index.js | 2 ++ app/vue/src/client/preview/render.js | 8 ++++---- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/angular/src/client/preview/index.js b/app/angular/src/client/preview/index.js index e24954c17850..be920eba40a7 100644 --- a/app/angular/src/client/preview/index.js +++ b/app/angular/src/client/preview/index.js @@ -53,3 +53,5 @@ const renderUI = () => { }; reduxStore.subscribe(renderUI); + +export const forceReRender = () => render(context, true); diff --git a/app/angular/src/client/preview/render.js b/app/angular/src/client/preview/render.js index f7f8e71ba624..d53d95342278 100644 --- a/app/angular/src/client/preview/render.js +++ b/app/angular/src/client/preview/render.js @@ -22,7 +22,7 @@ export function renderException(error) { logger.error(error.stack); } -export function renderMain(data, storyStore) { +export function renderMain(data, storyStore, forceRender) { if (storyStore.size() === 0) return null; const { selectedKind, selectedStory } = data; @@ -39,7 +39,7 @@ export function renderMain(data, storyStore) { // https://github.com/storybooks/react-storybook/issues/116 const reRender = selectedKind !== previousKind || previousStory !== selectedStory; - if (reRender) { + if (reRender || forceRender) { // We need to unmount the existing set of components in the DOM node. // Otherwise, React may not recrease instances for every story run. // This could leads to issues like below: @@ -54,14 +54,14 @@ export function renderMain(data, storyStore) { return renderNgApp(story, context, reRender); } -export default function renderPreview({ reduxStore, storyStore }) { +export default function renderPreview({ reduxStore, storyStore }, forceRender = false) { const state = reduxStore.getState(); if (state.error) { return renderException(state.error); } try { - return renderMain(state, storyStore); + return renderMain(state, storyStore, forceRender); } catch (ex) { return renderException(ex); } diff --git a/app/react/src/client/preview/index.js b/app/react/src/client/preview/index.js index b241e551227e..733711486350 100644 --- a/app/react/src/client/preview/index.js +++ b/app/react/src/client/preview/index.js @@ -22,11 +22,7 @@ const isBrowser = const storyStore = new StoryStore(); /* eslint-disable no-underscore-dangle */ -const reduxStore = createStore( - reducer, - window.__REDUX_DEVTOOLS_EXTENSION__ && - window.__REDUX_DEVTOOLS_EXTENSION__({ name: 'Storybook Preview', instanceId: 'sbPreview' }) -); +const reduxStore = createStore(reducer); /* eslint-enable */ const context = { storyStore, reduxStore }; diff --git a/app/vue/src/client/preview/index.js b/app/vue/src/client/preview/index.js index 32a10109a781..a3d7bf380ba0 100644 --- a/app/vue/src/client/preview/index.js +++ b/app/vue/src/client/preview/index.js @@ -54,3 +54,5 @@ const renderUI = () => { }; reduxStore.subscribe(renderUI); + +export const forceReRender = () => render(context, true); diff --git a/app/vue/src/client/preview/render.js b/app/vue/src/client/preview/render.js index ae5e4cf16112..caf6a9a8365c 100644 --- a/app/vue/src/client/preview/render.js +++ b/app/vue/src/client/preview/render.js @@ -49,7 +49,7 @@ function renderRoot(options) { app = new Vue(options); } -export function renderMain(data, storyStore) { +export function renderMain(data, storyStore, forceRender) { if (storyStore.size() === 0) return; const { selectedKind, selectedStory } = data; @@ -60,7 +60,7 @@ export function renderMain(data, storyStore) { // renderMain() gets executed after each action. Actions will cause the whole // story to re-render without this check. // https://github.com/storybooks/react-storybook/issues/116 - if (selectedKind !== previousKind || previousStory !== selectedStory) { + if (forceRender || selectedKind !== previousKind || previousStory !== selectedStory) { // We need to unmount the existing set of components in the DOM node. // Otherwise, React may not recrease instances for every story run. // This could leads to issues like below: @@ -97,14 +97,14 @@ export function renderMain(data, storyStore) { }); } -export default function renderPreview({ reduxStore, storyStore }) { +export default function renderPreview({ reduxStore, storyStore }, forceRender = false) { const state = reduxStore.getState(); if (state.error) { return renderException(state.error); } try { - return renderMain(state, storyStore); + return renderMain(state, storyStore, forceRender); } catch (ex) { return renderException(ex); } From 31a68d7b90b8930bb046600c636e5abdfee373ef Mon Sep 17 00:00:00 2001 From: Dan Green Date: Wed, 27 Dec 2017 11:15:36 -0500 Subject: [PATCH 5/5] (#1736) Update Force ReRender storyshot --- .../stories/__snapshots__/force-rerender.stories.storyshot | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 examples/cra-kitchen-sink/src/stories/__snapshots__/force-rerender.stories.storyshot diff --git a/examples/cra-kitchen-sink/src/stories/__snapshots__/force-rerender.stories.storyshot b/examples/cra-kitchen-sink/src/stories/__snapshots__/force-rerender.stories.storyshot new file mode 100644 index 000000000000..fd64ff4e772b --- /dev/null +++ b/examples/cra-kitchen-sink/src/stories/__snapshots__/force-rerender.stories.storyshot @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Storyshots Force ReRender button 1`] = ` + +`;