attach API
import { attach } from "effector";Метод attach позволяет создавать новые эффекты на основе существующих c возможностью доступа к данным из стора. Этот метод позволяет переиспользовать логику эффектов с разными параметрами и автоматически передавать данные из сторов.
Прикрепленный эффект является таким же полноценным эффектом, который имеет собственные свойства .done, .fail, и др. Они срабатывают только при вызовах прикрепленного эффекта, а не оригинального.
const originalFx = createEffect(async (x: number) => x * 2);const attachedFx = attach({ effect: originalFx });
originalFx.done.watch(() => console.log("original done"));attachedFx.done.watch(() => console.log("attached done"));
await attachedFx(5);// original done// attached done
await originalFx(5);// original done// (attached done не сработает)Алгоритм работы
- Вы вызываете эффект, который вернул
attach, передав свои параметры. - Если указан
source, тогда Effector берёт текущее значение из этого стора. - Если указан
mapParams, вызывается эта функция с вашими параметрами и (если есть) данными изsource. - Результат функции
mapParamsпередаётся в оригинальный эффектeffect. - Возвращается результат выполнения оригинального эффекта.
Виды конфигураций attach
Форма | Описание |
|---|---|
attach({ effect }) | Создает локальную копию эффекта с тем же поведением. |
attach({ source, effect }) | Создает эффект, который автоматически передает данные из source в оригинальный эффект при вызове. |
attach({ mapParams, effect }) | Создает эффект с преобразованием входных параметров через функцию mapParams перед передачей в оригинальный эффект. |
attach({ source, mapParams, effect }) | Создает эффект, который комбинирует данные из source с входными параметрами через mapParams и передает результат в оригинальный эффект. |
Конфигурации
attach({ effect })
Создает новый прикрепленный эффект, который будет вызывать effect с переданными параметрами как есть. Это позволяет создавать отдельные эффекты с общим поведением.
- Формула
const attachedFx = attach({ effect, // оригинальный эффект чье поведение копируем name? // имя нового эффекта});- Тип
export function attach<FX extends Effect<any, any, any>>(config: { effect: FX; name?: string;}): Effect<EffectParams<FX>, EffectResult<FX>, EffectError<FX>>;- Примеры
Это позволяет создать локальную копию эффекта, чтобы реагировать только на вызовы из текущего локального кода.
// Общий эффект для всего приложенияconst sendAnalyticsFx = createEffect(async (event: { name: string; data: any }) => { console.log("Analytics:", event.name);});
// В модуле авторизации - локальная копияconst trackAuthFx = attach({ effect: sendAnalyticsFx, name: "trackAuthFx",});
// Обрабатываем только события из модуля авторизацииtrackAuthFx.done.watch(() => { console.log("Auth event tracked");});
// В модуле корзины - другая локальная копияconst trackCartFx = attach({ effect: sendAnalyticsFx, name: "trackCartFx",});
// Обрабатываем только события из модуля корзиныtrackCartFx.done.watch(() => { console.log("Cart event tracked");});
trackAuthFx({ name: "login", data: {} });// Analytics: login// Auth event tracked
trackCartFx({ name: "add_to_cart", data: {} });// Analytics: add_to_cart// Cart event trackedattach({ source, effect })
Создает новый прикрепленный эффект, который при вызове будет запускать оригинальный эффект effect или обработчик с данными из source.
- Формула
const attachedFx = attach({ source, // источник данных передаваемый в эффект effect, // оригинальный эффект чье поведение копируем name? // имя нового эффекта domain? //домен, в случае если effect это обработчик});- Тип
export function attach< States extends StoreShape, FX extends | Effect<GetShapeValue<States>, any, any> | ((state: GetShapeValue<States>, ...params: any[]) => any),>(config: { source: States; effect: FX; name?: string; domain?: Domain;}): Effect<void, EffectResult<FX>, EffectError<FX>>;-
Особенности
- Аргумент
effectможет быть как эффектом, так и обычным обработчиком. - Аргумент
sourceне является реактивным - изменения сторов не вызывают автоматический запуск эффекта. sourceможет быть стором, объектом сторов или массивом сторов.- Параметр
domainможет быть передан только в случае, еслиeffectявляется обработчиком.
- Аргумент
-
Примеры
Простое использование с одним стором и обработчиком:
// Эффект для загрузки данныхconst loadDataFx = createEffect(async (id: number) => { return fetch(`/api/data/${id}`).then((res) => res.json());});
// Стор с текущим idconst $currentId = createStore(1);
// Эффект с привязкой стораconst loadCurrentDataFx = attach({ source: $currentId, effect: async (id: number) => { const res = await fetch(`/api/data/${id}`); return await res.json(); },});Аргумент source как объект:
import { createEffect, createStore, attach } from "effector";
const requestPageFx = createEffect<{ page: number; size: number }, number>( async ({ page, size }) => { console.log("Запрошено", page); return page * size; },);
const $page = createStore(1);const $size = createStore(20);
const requestNextPageFx = attach({ source: { page: $page, size: $size }, effect: requestPageFx,});
$page.on(requestNextPageFx.done, (page) => page + 1);
requestPageFx.doneData.watch((position) => console.log("requestPageFx.doneData", position));
await requestNextPageFx();// => Запрошено 1// => requestPageFx.doneData 20Использование с массивом сторов:
const $lat = createStore(55.7558);const $lon = createStore(37.6173);
// Эффект получения погодыconst fetchWeatherFx = createEffect(([lat, lon]: [number, number]) => fetch(`/api/weather?lat=${lat}&lon=${lon}`).then((res) => res.json()),);
// Объединение массива сторовconst loadWeatherFx = attach({ source: combine([$lat, $lon]), effect: fetchWeatherFx,});- Возвращаемое значение
Возвращает новый эффект.
attach({ mapParams, effect })
Создает новый прикрепленный эффект, который при вызове будет запускать оригинальный эффект effect, преобразуя параметры с помощью функции mapParams.
- Формула
const attachedFx = attach({ effect, // оригинальный эффект чье поведение копируем mapParams, // функция для преобразования данных name? // имя нового эффекта});- Тип
export function attach<Params, FX extends Effect<any, any, any>>(config: { effect: FX; mapParams: (params: Params) => EffectParams<FX>; name?: string;}): Effect<Params, EffectResult<FX>, EffectError<FX>>;-
Особенности
- Если
mapParamsзавершится с ошибкой, тогда прикрепленный эффект сразу завершит свое выполнение, а оригинальный эффект не вызовется. mapParamsдолжна возвращать тот же тип, который принимаетoriginalFxв качестве параметров. В случае ошибки вам нужно самому проконтролировать совместимость типов ошибок с эффектом, TypeScript здесь не поможет.
const attachedFx: Effect<void, Done, Fail> = attach({effect: originalFx,mapParams: (): A {throw new AnyNonFailType(); // Это может быть несовместимо с типом `Fail`.},}); - Если
-
Примеры
С помощью mapParams можно преобразовать аргументы:
import { createEffect, attach } from "effector";
const originalFx = createEffect((a: { input: number }) => a);
const attachedFx = attach({ effect: originalFx, mapParams(a: number) { return { input: a * 100 }; },});
originalFx.watch((params) => console.log("originalFx started", params));
attachedFx(1);// => originalFx { input: 100 }А также обрабатывать исключения:
import { createEffect, attach } from "effector";
const originalFx = createEffect((a: { a: number }) => a);
const attachedFx = attach({ effect: originalFx, mapParams(a: number) { throw new Error("custom error"); return { a }; },});
attachedFx.failData.watch((error) => console.log("attachedFx.failData", error));
attachedFx(1);// => attachedFx.failData// => Error: custom error- Возвращаемое значение
Возвращает новый эффект.
attach({ source, mapParams, effect })
Создает новый прикрепленный эффект, который будет читать значения из source стора, передавать их с параметрами в функцию mapParams, а затем вызывать effect с результатом.
- Формула
const attachedFx = attach({ source, // источник данных передаваемый в эффект mapParams, // функция для преобразования данных effect, // оригинальный эффект чье поведение копируем name? // имя нового эффекта});- Тип
export function attach< States extends StoreShape, FX extends Effect<any, any, any>, FN extends (params: any, source: GetShapeValue<States>) => EffectParams<FX>,>(config: { source: States; effect: FX; mapParams: FN; name?: string;}): Effect<Parameters<FN>[0], EffectResult<FX>, EffectError<FX>>;-
Особенности
- Если
mapParamsзавершится с ошибкой, тогда прикрепленный эффект сразу завершит свое выполнение, а оригинальный эффект не вызовется. - Функция
mapParamsдолжна возвращать тот же тип, который принимает эффект в аргументеeffectв качестве параметров. В случае ошибки вам нужно самому проконтролировать совместимость типов ошибок с эффектом, TypeScript здесь не поможет. - Аргумент
sourceне является реактивным - изменения сторов не вызывают автоматический запуск эффекта. sourceможет быть стором, объектом сторов или массивом сторов.
- Если
-
Примеры
import { createStore, createEvent, createEffect, attach, sample } from "effector";
const $credentials = createStore({ username: "", password: "" });const $authToken = createStore("");
const apiFx = createEffect(async ({ url, data, token }) => { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", Authorization: token ? `Bearer ${token}` : "", }, body: JSON.stringify(data), }); return response.json();});
const loginFx = attach({ source: { creds: $credentials, token: $authToken }, mapParams: (_, { creds, token }) => ({ url: "/api/login", data: creds, token, }), effect: apiFx,});- Возвращаемое значение
Возвращает новый эффект.
Связанные API и статьи
- API
Effect API- Описание эффектов, его методов и свойствcreateEffect- Создание нового эффектаsample- Ключевой оператор для построения связей между юнитамиStore API- Описание сторов, его методов и свойств
- Статьи
Документация на английском языке - самая актуальная, поскольку её пишет и обновляет команда effector. Перевод документации на другие языки осуществляется сообществом по мере наличия сил и желания.
Помните, что переведенные статьи могут быть неактуальными, поэтому для получения наиболее точной и актуальной информации рекомендуем использовать оригинальную англоязычную версию документации.