Last active
February 19, 2025 07:18
-
-
Save longdog/eb9582243f4ddff85dce466d8299c0bf to your computer and use it in GitHub Desktop.
effector fetch and cache
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 })) | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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