diff --git a/code/lib/manager-api/src/index.tsx b/code/lib/manager-api/src/index.tsx index ab247114e440..bb7fe0e5ec6c 100644 --- a/code/lib/manager-api/src/index.tsx +++ b/code/lib/manager-api/src/index.tsx @@ -386,30 +386,34 @@ export function useParameter(parameterKey: string, defaultValue?: S) { } // cache for taking care of HMR -const addonStateCache: { - [key: string]: any; -} = {}; +globalThis.STORYBOOK_ADDON_STATE = {}; +const { STORYBOOK_ADDON_STATE } = globalThis; // shared state export function useSharedState(stateId: string, defaultState?: S) { const api = useStorybookApi(); - const existingState = api.getAddonState(stateId) || addonStateCache[stateId]; + const existingState = api.getAddonState(stateId) || STORYBOOK_ADDON_STATE[stateId]; const state = orDefault( existingState, - addonStateCache[stateId] ? addonStateCache[stateId] : defaultState + STORYBOOK_ADDON_STATE[stateId] ? STORYBOOK_ADDON_STATE[stateId] : defaultState ); + let quicksync = false; + + if (state === defaultState && defaultState !== undefined) { + STORYBOOK_ADDON_STATE[stateId] = defaultState; + quicksync = true; + } + useEffect(() => { - if (api.getAddonState(stateId) === undefined && api.getAddonState(stateId) !== state) { - api.setAddonState(stateId, state).then((s) => { - addonStateCache[stateId] = s; - }); + if (quicksync) { + api.setAddonState(stateId, defaultState); } - }, [api]); + }); const setState = (s: S | API_StateMerger, options?: Options) => { const result = api.setAddonState(stateId, s, options); - addonStateCache[stateId] = result; + STORYBOOK_ADDON_STATE[stateId] = result; return result; }; const allListeners = useMemo(() => { @@ -421,17 +425,17 @@ export function useSharedState(stateId: string, defaultState?: S) { [SET_STORIES]: async () => { const currentState = api.getAddonState(stateId); if (currentState) { - addonStateCache[stateId] = currentState; + STORYBOOK_ADDON_STATE[stateId] = currentState; api.emit(`${SHARED_STATE_SET}-manager-${stateId}`, currentState); - } else if (addonStateCache[stateId]) { + } else if (STORYBOOK_ADDON_STATE[stateId]) { // this happens when HMR - await setState(addonStateCache[stateId]); - api.emit(`${SHARED_STATE_SET}-manager-${stateId}`, addonStateCache[stateId]); + await setState(STORYBOOK_ADDON_STATE[stateId]); + api.emit(`${SHARED_STATE_SET}-manager-${stateId}`, STORYBOOK_ADDON_STATE[stateId]); } else if (defaultState !== undefined) { // if not HMR, yet the defaults are from the manager await setState(defaultState); - // initialize addonStateCache after first load, so its available for subsequent HMR - addonStateCache[stateId] = defaultState; + // initialize STORYBOOK_ADDON_STATE after first load, so its available for subsequent HMR + STORYBOOK_ADDON_STATE[stateId] = defaultState; api.emit(`${SHARED_STATE_SET}-manager-${stateId}`, defaultState); } }, diff --git a/code/lib/manager-api/src/modules/addons.ts b/code/lib/manager-api/src/modules/addons.ts index 0e1d69ca39e5..4f618a23b7ff 100644 --- a/code/lib/manager-api/src/modules/addons.ts +++ b/code/lib/manager-api/src/modules/addons.ts @@ -146,7 +146,7 @@ export const init: ModuleFn = ({ provider, store, fullAPI }) = .then(() => api.getAddonState(addonId)); }, getAddonState: (addonId) => { - return store.getState().addons[addonId]; + return store.getState().addons[addonId] || globalThis?.STORYBOOK_ADDON_STATE[addonId]; }, }; diff --git a/code/lib/manager-api/src/typings.d.ts b/code/lib/manager-api/src/typings.d.ts index 1d0d8d33ff0e..b7de89a44b4e 100644 --- a/code/lib/manager-api/src/typings.d.ts +++ b/code/lib/manager-api/src/typings.d.ts @@ -6,3 +6,4 @@ declare var FEATURES: import('@storybook/types').StorybookConfig['features']; declare var REFS: any; declare var VERSIONCHECK: any; declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined; +declare var STORYBOOK_ADDON_STATE: Record;