Skip to content

Commit

Permalink
Merge pull request #2605 from storybooks/tmeasday/add-revisions-to-re…
Browse files Browse the repository at this point in the history
…factor

Use store revisions to ensure that stories re-render on HMR.
  • Loading branch information
shilman authored Dec 30, 2017
2 parents 0fefa98 + 10ed61d commit 9c3ec7f
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
27 changes: 19 additions & 8 deletions app/react/src/client/preview/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const logger = console;
let rootEl = null;
let previousKind = '';
let previousStory = '';
let previousRevision = -1;

if (isBrowser) {
rootEl = document.getElementById('root');
Expand Down Expand Up @@ -46,6 +47,7 @@ export function renderMain(data, storyStore) {
const noPreview = <NoPreview />;
const { selectedKind, selectedStory } = data;

const revision = storyStore.getRevision();
const story = storyStore.getStory(selectedKind, selectedStory);
if (!story) {
ReactDOM.render(noPreview, rootEl);
Expand All @@ -56,16 +58,25 @@ 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) {
// 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:
// https://github.com/storybooks/react-storybook/issues/81
previousKind = selectedKind;
previousStory = selectedStory;
ReactDOM.unmountComponentAtNode(rootEl);
// However, we do want the story to re-render if the store itself has changed
// (which happens at the moment when HMR occurs)
if (
revision === previousRevision &&
selectedKind === previousKind &&
previousStory === selectedStory
) {
return null;
}

// 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:
// https://github.com/storybooks/react-storybook/issues/81
previousRevision = revision;
previousKind = selectedKind;
previousStory = selectedStory;
ReactDOM.unmountComponentAtNode(rootEl);

const context = {
kind: selectedKind,
story: selectedStory,
Expand Down
1 change: 1 addition & 0 deletions lib/core/src/client/preview/client_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export default class ClientApi {
if (m && m.hot) {
m.hot.dispose(() => {
this._storyStore.removeStoryKind(kind);
this._storyStore.incrementRevision();
});
}

Expand Down
14 changes: 13 additions & 1 deletion lib/core/src/client/preview/story_store.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ export default class StoryStore extends EventEmitter {
constructor() {
super();
this._data = {};
this._revision = 0;
}

getRevision() {
return this._revision;
}

incrementRevision() {
this._revision += 1;
}

addStory(kind, name, fn, fileName) {
Expand Down Expand Up @@ -88,7 +97,10 @@ export default class StoryStore extends EventEmitter {
}

dumpStoryBook() {
const data = this.getStoryKinds().map(kind => ({ kind, stories: this.getStories(kind) }));
const data = this.getStoryKinds().map(kind => ({
kind,
stories: this.getStories(kind),
}));

return data;
}
Expand Down

0 comments on commit 9c3ec7f

Please sign in to comment.