diff --git a/core/store/src/state/context/components.ts b/core/store/src/state/context/components.ts index 410882229..b74f51f9c 100644 --- a/core/store/src/state/context/components.ts +++ b/core/store/src/state/context/components.ts @@ -8,6 +8,7 @@ import { import { useStore } from './store'; import { useStory, useCurrentStory } from './story'; import { useCurrentDocument } from './document'; +import { useMemo } from 'react'; export interface ComponentInputProps { /** @@ -33,78 +34,80 @@ export const useComponents = ({ const store = useStore(); const story = useStory({ id: name }); const currentDoc = useCurrentDocument(); - const { component: storyComponentName } = story || {}; - const storyComponent = getComponentName(storyComponentName); - const doc = story && story.doc ? store.docs[story.doc] : currentDoc; - const component = - storyComponent && doc && doc.componentsLookup - ? store.components[doc.componentsLookup[storyComponent]] - : undefined; + return useMemo(() => { + const { component: storyComponentName } = story || {}; + const storyComponent = getComponentName(storyComponentName); + const doc = story && story.doc ? store.docs[story.doc] : currentDoc; + const component = + storyComponent && doc && doc.componentsLookup + ? store.components[doc.componentsLookup[storyComponent]] + : undefined; - let components: Components | undefined = undefined; - const getComponents = ( - components: { [key: string]: any } | undefined, - ): Components => { - const getComponent = (name: string) => - doc?.componentsLookup?.[name] && - store?.components[doc.componentsLookup[name]]; - return store && doc && components - ? Object.keys(components).reduce((acc, key) => { - const comp = components[key]; - if (comp === CURRENT_STORY) { - const comps: Record = {}; - const name = getComponentName(doc.component); + let components: Components | undefined = undefined; + const getComponents = ( + components: { [key: string]: any } | undefined, + ): Components => { + const getComponent = (name: string) => + doc?.componentsLookup?.[name] && + store?.components[doc.componentsLookup[name]]; + return store && doc && components + ? Object.keys(components).reduce((acc, key) => { + const comp = components[key]; + if (comp === CURRENT_STORY) { + const comps: Record = {}; + const name = getComponentName(doc.component); + if (name) { + const component = getComponent(name); + if (component) { + comps[name] = component; + } + } + if (doc.subcomponents) { + Object.keys(doc.subcomponents).forEach(subKey => { + const name = getComponentName(doc.subcomponents?.[subKey]); + if (name) { + const component = getComponent(name); + if (component) { + comps[name] = component; + } + } + }); + } + return { ...acc, ...comps }; + } + const keys = doc.componentsLookup + ? Object.keys(doc.componentsLookup) + : []; + const name = keys.length === 1 ? keys[0] : getComponentName(comp); if (name) { const component = getComponent(name); if (component) { - comps[name] = component; + return { ...acc, [key]: component }; } } - if (doc.subcomponents) { - Object.keys(doc.subcomponents).forEach(subKey => { - const name = getComponentName(doc.subcomponents?.[subKey]); - if (name) { - const component = getComponent(name); - if (component) { - comps[name] = component; - } - } - }); - } - return { ...acc, ...comps }; - } - const keys = doc.componentsLookup - ? Object.keys(doc.componentsLookup) - : []; - const name = keys.length === 1 ? keys[0] : getComponentName(comp); - if (name) { - const component = getComponent(name); - if (component) { - return { ...acc, [key]: component }; - } - } - return acc; - }, {}) - : {}; - }; - if (of === CURRENT_STORY && story) { - if (component) { - const name = getComponentName(component); - if (name) { - components = { - [name]: component, - ...getComponents(story.subcomponents), - }; + return acc; + }, {}) + : {}; + }; + if (of === CURRENT_STORY && story) { + if (component) { + const name = getComponentName(component); + if (name) { + components = { + [name]: component, + ...getComponents(story.subcomponents), + }; + } else { + components = getComponents(story.subcomponents); + } } else { components = getComponents(story.subcomponents); } } else { - components = getComponents(story.subcomponents); + components = getComponents({ of }); } - } else { - components = getComponents({ of }); - } - return components; + return components; + }, [currentDoc, of, store, story]); }; /** @@ -118,17 +121,19 @@ export const useComponent = ({ const story = useStory({ id: name }); const currentDoc = useCurrentDocument(); const store = useStore(); - const doc = story && story.doc ? store.docs[story.doc] : currentDoc; - let component; - if (of === CURRENT_STORY) { - component = story ? story.component : doc?.component; - } else { - component = of; - } - const componentName = getComponentName(component); - return componentName && doc && doc.componentsLookup - ? store.components[doc.componentsLookup[componentName]] - : undefined; + return useMemo(() => { + const doc = story && story.doc ? store.docs[story.doc] : currentDoc; + let component; + if (of === CURRENT_STORY) { + component = story ? story.component : doc?.component; + } else { + component = of; + } + const componentName = getComponentName(component); + return componentName && doc && doc.componentsLookup + ? store.components[doc.componentsLookup[componentName]] + : undefined; + }, [currentDoc, of, store, story]); }; /** @@ -141,12 +146,16 @@ export const useCurrentPropsCount = (): number => { const story = useCurrentStory(); const components = useComponents({ name: story?.id }); const doc = useCurrentDocument(); - return components && doc - ? Object.keys(components).reduce((acc, key) => { - const component = doc.componentsLookup - ? store.components[doc.componentsLookup[key]] - : undefined; - return acc + Object.keys(component?.info?.props || {}).length; - }, 0) - : 0; + return useMemo( + () => + components && doc + ? Object.keys(components).reduce((acc, key) => { + const component = doc.componentsLookup + ? store.components[doc.componentsLookup[key]] + : undefined; + return acc + Object.keys(component?.info?.props || {}).length; + }, 0) + : 0, + [components, doc, store], + ); }; diff --git a/core/store/src/state/context/document.tsx b/core/store/src/state/context/document.tsx index 68eb3a6d4..80f995c12 100644 --- a/core/store/src/state/context/document.tsx +++ b/core/store/src/state/context/document.tsx @@ -129,26 +129,28 @@ export const useDocSort = ( return [sort[type] || 'date', newSort => setSort(type, newSort)]; }; +const getDocsByType = (docs: Documents, type: DocType) => + Object.keys(docs).reduce((acc: Pages, key: string) => { + const doc: Document | undefined = docs[key]; + if (doc) { + const { type: docType = defDocType } = doc; + if (docType === type) { + return [...acc, { ...doc }]; + } + } + return acc; + }, []); /** * Returns an array of all documents of a specific doc type */ export const useDocByType = (type: DocType): Pages => { - return useGetDocByType()(type); + const docs = useDocs(); + return useMemo(() => getDocsByType(docs, type), [docs, type]); }; export const useGetDocByType = (): ((type: DocType) => Pages) => { const docs = useDocs(); - return (type: DocType) => - Object.keys(docs).reduce((acc: Pages, key: string) => { - const doc: Document | undefined = docs[key]; - if (doc) { - const { type: docType = defDocType } = doc; - if (docType === type) { - return [...acc, { ...doc }]; - } - } - return acc; - }, []); + return (type: DocType) => getDocsByType(docs, type); }; /** @@ -157,7 +159,7 @@ export const useGetDocByType = (): ((type: DocType) => Pages) => { export const useSortedDocByType = (type: DocType): Pages => { const docs = useDocByType(type); const [sort] = useDocSort(type); - return [...docs].sort(docSortFn(sort)); + return useMemo(() => [...docs].sort(docSortFn(sort)), [docs, sort]); }; export type DocCountType = Record; diff --git a/core/store/src/state/context/story.tsx b/core/store/src/state/context/story.tsx index db2261815..936c4616b 100644 --- a/core/store/src/state/context/story.tsx +++ b/core/store/src/state/context/story.tsx @@ -2,6 +2,7 @@ import React, { FC, createContext, useContext, + useMemo, useState, useEffect, } from 'react'; @@ -103,16 +104,18 @@ export const useStoryById = (storyId: string): Story | undefined => { */ export const useStoryIdFromName = (name?: string): string | undefined => { const store = useStore(); - if (name) { - for (const docId in store.docs) { - const doc = store.docs[docId]; - const storyId = docStoryToId(docId, name); - if (doc.stories && doc.stories.indexOf(storyId) > -1) { - return storyId; + return useMemo(() => { + if (name) { + for (const docId in store.docs) { + const doc = store.docs[docId]; + const storyId = docStoryToId(docId, name); + if (doc.stories && doc.stories.indexOf(storyId) > -1) { + return storyId; + } } } - } - return undefined; + return undefined; + }, [name, store.docs]); }; export interface StoryInputProps { @@ -166,16 +169,20 @@ export const useStoryComponent = ( ): Component | undefined => { const storyId = useStoryId(props); const store = useStore(); - const story: Story | undefined = storyId ? store.stories[storyId] : undefined; - const storyComponent: any = story?.component; - - const componentName = getComponentName(storyComponent); - const doc = story && story.doc ? store.docs[story.doc] : undefined; - const component = - componentName && doc?.componentsLookup?.[componentName] - ? store.components[doc.componentsLookup[componentName]] + return useMemo(() => { + const story: Story | undefined = storyId + ? store.stories[storyId] : undefined; - return component; + const storyComponent: any = story?.component; + + const componentName = getComponentName(storyComponent); + const doc = story && story.doc ? store.docs[story.doc] : undefined; + const component = + componentName && doc?.componentsLookup?.[componentName] + ? store.components[doc.componentsLookup[componentName]] + : undefined; + return component; + }, [store, storyId]); }; /**