From 53c73bf65edaebdf9c7acde2cb190b74592b1d73 Mon Sep 17 00:00:00 2001 From: MatthewPattell Date: Thu, 8 Aug 2024 16:28:27 +0200 Subject: [PATCH] feat: add failed store creation strategy --- src/manager.ts | 18 +++++++++++++++--- src/types.ts | 8 ++++++++ src/with-stores.tsx | 43 +++++++++++++++++++++++-------------------- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/manager.ts b/src/manager.ts index 3fb874c..c4eb0f3 100644 --- a/src/manager.ts +++ b/src/manager.ts @@ -75,6 +75,7 @@ class Manager { public readonly options: IManagerOptions = { shouldDisablePersist: false, shouldRemoveInitState: true, + failedCreationStrategy: 'empty', }; /** @@ -337,6 +338,8 @@ class Manager { componentName: string, componentProps: Record = {}, ): IGroupedStores { + const { failedCreationStrategy } = this.options; + const result = map.reduce( (res, [key, store]) => { const { @@ -344,7 +347,7 @@ class Manager { store: s, isParent = false, } = 'store' in store ? store : { store, id: undefined, isParent: false }; - const storeId = + let storeId = id || (isParent ? (this.getStore(s, { contextId, parentId })?.libStoreId as string) @@ -360,7 +363,16 @@ class Manager { true, ); - return res; + if (failedCreationStrategy === 'dummy') { + // try to force create store + storeId = this.getStoreId(s, { key, contextId }); + } else { + if (failedCreationStrategy === 'empty') { + res.hasCreationFailure = true; + } + + return res; + } } const storeInstance = this.createStore(s, { @@ -382,7 +394,7 @@ class Manager { return res; }, - { relativeStores: {}, parentStores: {}, globalStores: {} }, + { relativeStores: {}, parentStores: {}, globalStores: {}, hasCreationFailure: false }, ); // need create context relation in case when component doesn't include relative stores diff --git a/src/types.ts b/src/types.ts index a354574..11f4311 100644 --- a/src/types.ts +++ b/src/types.ts @@ -94,6 +94,13 @@ export interface IManagerOptions { touched?: number; // NOTE: set to max timeout request unused?: number; }; + /** + * When for some strange reason stores cannot be created or found in the parent context: + * none: don't do anything + * dummy: force create empty store + * empty (default): don't render component if any of the stores not created + */ + failedCreationStrategy: 'none' | 'dummy' | 'empty'; } export type TAnyStore = IStore | IStorePersisted; @@ -149,6 +156,7 @@ export interface IGroupedStores { relativeStores: TStores; parentStores: TStores; globalStores: TStores; + hasCreationFailure: boolean; } export interface IPersistOptions { diff --git a/src/with-stores.tsx b/src/with-stores.tsx index 260a85a..f9398fa 100644 --- a/src/with-stores.tsx +++ b/src/with-stores.tsx @@ -23,32 +23,35 @@ const withStores = , TS extends TMapStores>( const parentId = useStoreManagerParent(); const { suspenseId } = useConsistentSuspense(); const id = useId(); - const [{ contextId, componentStores, touchableStores, mountStores }] = useState(() => { - const ctxId = manualContextId || id; - const groupedStores = storeManager.createStores( - Object.entries(stores), - parentId, - ctxId, - suspenseId, - componentName, - props, - ); - const { globalStores, relativeStores, parentStores } = groupedStores; - const tStores = { ...relativeStores, ...globalStores }; + const [{ contextId, hasFailure, touchableStores, componentStores, mountStores }] = useState( + () => { + const ctxId = manualContextId || id; + const groupedStores = storeManager.createStores( + Object.entries(stores), + parentId, + ctxId, + suspenseId, + componentName, + props, + ); + const { globalStores, relativeStores, parentStores, hasCreationFailure } = groupedStores; + const tStores = { ...relativeStores, ...globalStores }; - return { - touchableStores: tStores, - componentStores: { ...tStores, ...parentStores }, - contextId: ctxId, - mountStores: () => storeManager.mountStores(ctxId, groupedStores), - }; - }); + return { + contextId: ctxId, + hasFailure: hasCreationFailure, + touchableStores: tStores, + componentStores: { ...tStores, ...parentStores }, + mountStores: () => storeManager.mountStores(ctxId, groupedStores), + }; + }, + ); useEffect(mountStores, [mountStores]); return ( - + {!hasFailure && } ); };