Skip to content

Commit

Permalink
feat: add failed store creation strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
MatthewPattell committed Aug 8, 2024
1 parent adf35fe commit 53c73bf
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 23 deletions.
18 changes: 15 additions & 3 deletions src/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class Manager {
public readonly options: IManagerOptions = {
shouldDisablePersist: false,
shouldRemoveInitState: true,
failedCreationStrategy: 'empty',
};

/**
Expand Down Expand Up @@ -337,14 +338,16 @@ class Manager {
componentName: string,
componentProps: Record<string, any> = {},
): IGroupedStores {
const { failedCreationStrategy } = this.options;

const result = map.reduce(
(res, [key, store]) => {
const {
id,
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)
Expand All @@ -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, {
Expand All @@ -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
Expand Down
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -149,6 +156,7 @@ export interface IGroupedStores {
relativeStores: TStores;
parentStores: TStores;
globalStores: TStores;
hasCreationFailure: boolean;
}

export interface IPersistOptions {
Expand Down
43 changes: 23 additions & 20 deletions src/with-stores.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,35 @@ const withStores = <T extends Record<string, any>, 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 (
<StoreManagerParentProvider parentId={contextId} touchableStores={touchableStores}>
<ObservableComponent {...props} {...componentStores} />
{!hasFailure && <ObservableComponent {...props} {...componentStores} />}
</StoreManagerParentProvider>
);
};
Expand Down

0 comments on commit 53c73bf

Please sign in to comment.