attach API

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 не сработает)

Алгоритм работы

  1. Вы вызываете эффект, который вернул attach, передав свои параметры.
  2. Если указан source, тогда Effector берёт текущее значение из этого стора.
  3. Если указан mapParams, вызывается эта функция с вашими параметрами и (если есть) данными из source.
  4. Результат функции mapParams передаётся в оригинальный эффект effect.
  5. Возвращается результат выполнения оригинального эффекта.

Виды конфигураций 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 tracked

Запустить пример.

attach({ 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());
});
// Стор с текущим id
const $currentId = createStore(1);
// Эффект с привязкой стора
const loadCurrentDataFx = attach({
source: $currentId,
effect: async (id: number) => {
const res = await fetch(`/api/data/${id}`);
return await res.json();
},
});
  • Возвращаемое значение

Возвращает новый эффект.

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,
});
  • Возвращаемое значение

Возвращает новый эффект.

Перевод поддерживается сообществом

Документация на английском языке - самая актуальная, поскольку её пишет и обновляет команда effector. Перевод документации на другие языки осуществляется сообществом по мере наличия сил и желания.

Помните, что переведенные статьи могут быть неактуальными, поэтому для получения наиболее точной и актуальной информации рекомендуем использовать оригинальную англоязычную версию документации.

Соавторы