Skip to content

Commit

Permalink
fix: improve context performance
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed Apr 12, 2020
1 parent 95d071b commit 32024f2
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 87 deletions.
1 change: 0 additions & 1 deletion core/store/src/serialization/load-store.ts
Expand Up @@ -86,7 +86,6 @@ export const loadStoryStore = (): StoriesStore | undefined => {
story.controls || {},
);
}

if (kind.title && story.name) {
const id = toId(kind.title, storyNameFromExport(story.name));
if (!kind.stories) {
Expand Down
4 changes: 2 additions & 2 deletions integrations/storybook/src/panel/ControlsPanel.tsx
Expand Up @@ -12,7 +12,7 @@ export const ControlsPanel: React.FC<ControlsPanelProps> = ({
active,
api,
}) => {
const [storyId, setStoryId] = React.useState('');
const [storyId, setStoryId] = React.useState<string | undefined>();
const channel = React.useMemo(() => api.getChannel(), []);
React.useEffect(() => {
const onChangeStory = (props: any) => {
Expand All @@ -22,7 +22,7 @@ export const ControlsPanel: React.FC<ControlsPanelProps> = ({
return () => channel.off(SET_CURRENT_STORY, onChangeStory);
});

return active ? (
return active && storyId ? (
<BlockContextProvider storyId={storyId}>
<ControlsTable id="." />
</BlockContextProvider>
Expand Down
1 change: 0 additions & 1 deletion ui/blocks/src/BlockContainer/story/StoryBlockContainer.tsx
Expand Up @@ -40,7 +40,6 @@ export const StoryBlockContainer: FC<StoryBlockContainerProps> = ({
title: userTitle,
});
const block = children(context, rest);

return (
<BlockContainer
title={title}
Expand Down
18 changes: 7 additions & 11 deletions ui/blocks/src/Stories/Stories.tsx
@@ -1,5 +1,4 @@
import React, { FC } from 'react';
import { Story } from '@component-controls/specification';
import {
StoryBlockContainer,
StoryBlockContainerProps,
Expand All @@ -24,32 +23,29 @@ export type StoriesProps = StoriesOwnProps &
export const Stories: FC<StoriesProps> = props => (
<StoryBlockContainer {...props}>
{(context, rest) => {
const { story: selected, kind, getStory } = context;
const { story: selected, kind } = context;
const stories = kind?.stories
?.map((id: string) => getStory(id))
.filter(
(story?: Story) => !selected || (story && selected.id !== story.id),
);
? kind.stories.filter((id: string) => !selected || selected.id !== id)
: [];
if (!stories || !stories.length) {
return null;
}
return (
<>
{(stories as Story[]).map((story: Story) => {
const storyTitle = story.name;
{stories.map((id: string) => {
return (
<Playground
transform={{
options: {
disabled: true,
},
}}
title={storyTitle}
title="."
collapsible={false}
key={`playground-${story.id}`}
key={`playground-${id}`}
{...rest}
>
<StoryComponent id={story.id} />
<StoryComponent id={id} />
</Playground>
);
})}
Expand Down
44 changes: 9 additions & 35 deletions ui/blocks/src/context/block/BlockContext.tsx
@@ -1,6 +1,5 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import { store as storyStore, StoryStore } from '@component-controls/store';
import { Story } from '@component-controls/specification';
import { BlockDataContextProvider } from './BlockDataContext';
import { BlockControlsContextProvider } from './BlockControlsContext';

Expand All @@ -19,7 +18,11 @@ export interface BlockContextProps {
/**
* current story
*/
story?: Story;
storyId: string;
/**
* store interface
*/
storeProvider: StoryStore;
}
//@ts-ignore
export const BlockContext = React.createContext<BlockContextProps>({});
Expand All @@ -30,43 +33,14 @@ export const BlockContextProvider: React.FC<BlockContextInputProps> = ({
mockStore,
}) => {
const storeProvider = mockStore || storyStore;
const store = storeProvider.getStore();
const [story, setStory] = useState<{ story?: Story; id: string }>({
story: store ? store.stories[storyId] : undefined,
id: storyId,
});

const refreshData = () => {
setStory({
story: store ? { ...store.stories[storyId] } : undefined,
id: storyId,
});
};
useEffect(() => {
const onChange = (id?: string) => {
if (id === undefined || storyId === id) {
refreshData();
}
};
storyStore.addObserver(onChange);
return () => {
storyStore.removeObserver(onChange);
};
}, []);

useEffect(() => {
if (story.id !== storyId) {
refreshData();
}
}, [storyId, store]);

return (
<BlockContext.Provider
value={{
story: story.story,
storyId,
storeProvider,
}}
>
<BlockDataContextProvider store={store}>
<BlockDataContextProvider store={storeProvider}>
<BlockControlsContextProvider store={storeProvider}>
{children}
</BlockControlsContextProvider>
Expand Down
21 changes: 6 additions & 15 deletions ui/blocks/src/context/block/BlockDataContext.tsx
@@ -1,21 +1,16 @@
import React from 'react';
import { toId, storyNameFromExport } from '@storybook/csf';
import { StoryStore } from '@component-controls/store';
import {
Story,
StoriesStore,
StoryComponent,
StoryComponents,
StoriesKind,
getComponentName,
StoriesStore,
} from '@component-controls/specification';

export interface BlockDataContextProps {
/**
/**
* returns a story, given a story id
*/
getStory: (storyId?: string) => Story | undefined;

/**
* returns a story and its associated objects (kind, component), given a story id
*/
Expand All @@ -41,16 +36,15 @@ export interface BlockDataContextProps {
export const BlockDataContext = React.createContext<BlockDataContextProps>({});

export interface BlockDataContextInoutProps {
store?: StoriesStore;
store: StoryStore;
}

export const BlockDataContextProvider: React.FC<BlockDataContextInoutProps> = ({
children,
store,
store: storeProvider,
}) => {
/**
* returns a story and its file, given a story id
*/
const store: StoriesStore | undefined = storeProvider.getStore();

const getStoryData = (id?: string) => {
const story: Story | undefined =
store && store.stories && id ? store.stories[id] : undefined;
Expand All @@ -67,8 +61,6 @@ export const BlockDataContextProvider: React.FC<BlockDataContextInoutProps> = ({
: undefined;
return { story, kind, component };
};
const getStory = (id?: string) =>
store && store.stories && id && store.stories[id];

const getComponents = (
components: { [key: string]: any },
Expand Down Expand Up @@ -104,7 +96,6 @@ export const BlockDataContextProvider: React.FC<BlockDataContextInoutProps> = ({
return (
<BlockDataContext.Provider
value={{
getStory,
getStoryData,
storyIdFromName,
getComponents,
Expand Down
62 changes: 40 additions & 22 deletions ui/blocks/src/context/story/StoryContext.tsx
@@ -1,4 +1,4 @@
import React, { FC } from 'react';
import React, { FC, useState, useEffect } from 'react';
import {
Story,
StoriesKind,
Expand Down Expand Up @@ -34,38 +34,56 @@ export interface StoryContextProps {
* current story's/document's component
*/
component?: StoryComponent;

/**
* returns a story, given a story id
*/
getStory: (storyId?: string) => Story | undefined;
}

/**
*
* Context to be used by components that will display 'story' information
*/
export const useStoryContext = ({
id,
id = CURRENT_STORY,
name,
}: StoryInputProps): StoryContextProps => {
const { story: currentStory } = React.useContext(BlockContext);
const { getStoryData, getStory, storyIdFromName } = React.useContext(
BlockDataContext,
);
const currentId = currentStory ? currentStory.id : undefined;
const inputId = id === CURRENT_STORY ? currentId : id;
const storyId = inputId || (name && storyIdFromName(name)) || currentId;
if (!storyId) {
return { getStory };
}
const { story, kind, component } = getStoryData(storyId);
const { storyId: currentId, storeProvider } = React.useContext(BlockContext);
const { getStoryData, storyIdFromName } = React.useContext(BlockDataContext);
const storyId = name
? storyIdFromName(name)
: id === CURRENT_STORY
? currentId
: id;
const [data, setData] = useState<{
story?: Story;
kind?: StoriesKind;
component?: StoryComponent;
}>(getStoryData(storyId));

const updateData = () => {
const { story, kind, component } = getStoryData(storyId);
setData({ story, kind, component });
};
useEffect(() => {
const onChange = (id?: string) => {
if (storyId === id) {
updateData();
}
};
storeProvider.addObserver(onChange);

return () => {
storeProvider.removeObserver(onChange);
};
}, []);

useEffect(() => {
const { story } = data;
if (!story || story.id !== storyId) {
updateData();
}
}, [storyId]);

return {
id: storyId,
kind,
story,
component,
getStory,
...data,
};
};

Expand Down

0 comments on commit 32024f2

Please sign in to comment.