@virentia/effector API
@virentia/effector — пакет совместимости с API в стиле Effector.
createEvent
Используйте createEvent для событий и уведомлений в моделях Effector-стиля.
const submitted = createEvent<string>("submitted");
submitted.watch((value) => {
console.log(value);
});События поддерживают map, filter, filterMap и prepend.
const numbers = submitted.filterMap((value) => Number(value) || undefined);
const positive = numbers.filter((value) => value > 0);
const label = positive.map((value) => `#${value}`);createStore
Используйте createStore для состояния в scope с API в стиле Effector.
const incremented = createEvent<number>();
const reset = createEvent<void>();
const $count = createStore(0, { sid: "count" })
.on(incremented, (count, amount) => count + amount)
.reset(reset);Чтение и запись состояния:
$count.getState();
$count.setState(10);Сторы раскрывают updates, map, on, reset и watch.
createEffect
Используйте createEffect для асинхронной работы и юнитов жизненного цикла в стиле Effector.
const loadUserFx = createEffect<string, { id: string; name: string }>(async (id) => {
const response = await fetch(`/api/users/${id}`);
return response.json();
});Эффекты раскрывают:
loadUserFx.done;
loadUserFx.fail;
loadUserFx.finally;
loadUserFx.doneData;
loadUserFx.failData;
loadUserFx.pending;
loadUserFx.inFlight;Заменить или задать handler:
loadUserFx.use(async (id) => ({ id, name: "Ada" }));fork и allSettled
Используйте fork, чтобы создать scope. Используйте allSettled, чтобы запустить юнит внутри этого scope и дождаться асинхронной работы.
const appScope = fork({
values: {
count: 10,
},
});
await allSettled(incremented, {
scope: appScope,
params: 2,
});
console.log(appScope.getState($count)); // 12Эффекты возвращают объект со статусом:
const result = await allSettled(loadUserFx, {
scope: appScope,
params: "user:1",
});sample
Используйте sample, когда один юнит должен взять состояние другого юнита в момент срабатывания.
sample({
source: $count,
clock: submitted,
filter: (count) => count > 0,
fn: (count, text) => `${text}:${count}`,
target: saved,
});combine
Используйте combine, когда значение всегда выводится из нескольких сторов.
const $fullName = combine(
{ firstName: $firstName, lastName: $lastName },
({ firstName, lastName }) => `${firstName} ${lastName}`,
);split
Используйте split, когда одно событие нужно разложить по именованным веткам.
const routed = split(submitted, {
short: (text) => text.length < 10,
long: (text) => text.length >= 10,
});createApi и restore
Используйте restore, чтобы превратить payload события в состояние. Используйте createApi, чтобы создать несколько событий, обновляющих один стор.
const changed = createEvent<string>();
const $value = restore(changed, "");
const api = createApi($value, {
upper: (value) => value.toUpperCase(),
append: (value, suffix: string) => `${value}${suffix}`,
});attach
Используйте attach, когда вызову эффекта нужно добавить состояние из стора в params.
const authorizedFx = attach({
source: $token,
effect: requestFx,
mapParams: (id: number, token: string) => ({ id, token }),
});serialize и hydrate
Используйте это для переноса состояния scope между средами выполнения: обычно с сервера на клиент или из сохраненной сессии в новый scope.
const values = serialize(appScope);
const nextScope = fork();
hydrate(nextScope, { values });scopeBind
Используйте scopeBind, когда callback сработает позже, но должен запустить юнит в известном scope.
const boundSubmit = scopeBind(submitted, { scope: appScope });
await boundSubmit("hello");is
Используйте проверки из is во вспомогательных функциях, которые принимают неизвестные юниты.
is.unit(submitted);
is.event(submitted);
is.store($count);
is.effect(loadUserFx);
is.targetable($count);is.targetable возвращает true для вызываемых событий, writable-сторов и эффектов.