Skip to content

Instantly share code, notes, and snippets.

@longdog
Last active February 3, 2022 22:01
Show Gist options
  • Save longdog/eb9582243f4ddff85dce466d8299c0bf to your computer and use it in GitHub Desktop.
Save longdog/eb9582243f4ddff85dce466d8299c0bf to your computer and use it in GitHub Desktop.
effector fetch and cache
import { forward } from "effector";
import { createGate } from "effector-react";
import { createCached } from "store/helpers";
export const delegationSelectGage = createGate();
const [doFetch, $delegation, $loading] = createCached<void, Data[]>(
fetchDelegations,
"delegation"
);
forward({
from: delegationSelectGage.open,
to: doFetch,
});
export { $loading };
export const $delegationOptions = $delegation.map((sps) =>
sps?.map((s) => ({ label: s.title, value: s.id }))
);
import {
combine,
createDomain,
createEffect,
createEvent,
createStore,
Domain,
Event,
forward,
guard,
sample,
Store,
} from "effector";
import { createGate, Gate } from "effector-react";
export type CacheData = Record<string, any>;
export const $cache = createStore<CacheData | null>(null);
export const updateCache = createEvent<{ name: string; data: any }>();
export const clearCache = createEvent<string>();
$cache.on(updateCache, (prev, { name, data }) => ({ ...prev, [name]: data }));
$cache.on(clearCache, (prev, name) =>
prev
? Object.keys(prev)
.filter((key) => key !== name)
.reduce((obj: Record<string, any>, key) => {
obj[key] = prev[key];
return obj;
}, {})
: null
);
export function getFromCache<T>(name: string): Store<T> {
return $cache.map((c) => (c && !!c[name] ? c[name] : null)) as Store<T>;
}
export function createCached<RES, REQ>(
handle: (params: RES) => Promise<REQ>,
name: string
): [Event<RES>, Store<REQ | null>, Store<boolean>] {
const retStore = getFromCache<REQ | null>(name);
const doFetchNotCached = appDomain.createEvent<RES>();
const [doFetch, doneEvent, isLoading] = fetchModel<RES, REQ>(
handle,
appDomain
);
guard({
clock: doFetchNotCached,
filter: retStore.map((st) => !st),
target: doFetch,
});
forward({
from: doneEvent,
to: updateCache.prepend((data) => ({ name, data })),
});
return [doFetchNotCached, retStore, isLoading];
}
export function fetchModel<RES, REQ>(
handle: (params: RES) => Promise<REQ>,
domain: Domain,
errorTitle?: string
): [Event<RES>, Event<REQ>, Store<boolean>] {
const doFetch = domain.createEvent<RES>();
const fetchFx = domain.createEffect<RES, REQ | void>(handle);
forward({
from: doFetch,
to: fetchFx,
});
fetchFx.failData.watch((data) => {
console.log("ERROR", data);
});
const isLoading = fetchFx.pending;
const doneEvent = fetchFx.doneData as Event<REQ>;
return [doFetch, doneEvent, isLoading];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment