Source: Fix dynamic snippet updates

This commit is contained in:
Michael Shilman 2020-06-27 10:07:22 +08:00
parent 47a861ce6c
commit c28b90a434
2 changed files with 9 additions and 7 deletions

View File

@ -66,6 +66,7 @@
"core-js": "^3.0.1",
"doctrine": "^3.0.0",
"escodegen": "^1.12.0",
"fast-deep-equal": "^3.1.1",
"global": "^4.3.2",
"html-tags": "^3.1.0",
"js-beautify": "^1.8.8",

View File

@ -1,4 +1,5 @@
import React, { FC, Context, createContext, useEffect, useState } from 'react';
import deepEqual from 'fast-deep-equal';
import { addons } from '@storybook/addons';
import { StoryId } from '@storybook/api';
import { SNIPPET_RENDERED } from '../shared';
@ -18,9 +19,9 @@ export const SourceContainer: FC<{}> = ({ children }) => {
const channel = addons.getChannel();
const sourcesRef = React.useRef<StorySources>();
const handleAddJSX = (id: StoryId, newJsx: SourceItem) => {
if (newJsx !== sources[id]) {
const newSources = { ...sourcesRef.current, [id]: newJsx };
const handleSnippetRendered = (id: StoryId, newItem: SourceItem) => {
if (newItem !== sources[id]) {
const newSources = { ...sourcesRef.current, [id]: newItem };
sourcesRef.current = newSources;
}
};
@ -28,15 +29,15 @@ export const SourceContainer: FC<{}> = ({ children }) => {
// Bind this early (instead of inside `useEffect`), because the `SNIPPET_RENDERED` event
// is triggered *during* the rendering process, not after. We have to use the ref
// to ensure we don't end up calling setState outside the effect though.
channel.on(SNIPPET_RENDERED, handleAddJSX);
channel.on(SNIPPET_RENDERED, handleSnippetRendered);
useEffect(() => {
if (sourcesRef.current) {
if (!deepEqual(sources, sourcesRef.current)) {
setSources(sourcesRef.current);
}
return () => channel.off(SNIPPET_RENDERED, handleAddJSX);
}, [sources, setSources]);
return () => channel.off(SNIPPET_RENDERED, handleSnippetRendered);
});
return <SourceContext.Provider value={{ sources }}>{children}</SourceContext.Provider>;
};