sample API

import { sample } from "effector";

Метод для связывания юнитов. Его главная задача - брать данные из одного места source и передавать их в другое место target при срабатывании определённого триггера clock.

Типичный вариант использования – когда необходимо обработать какое-либо событие используя данные из стора. Вместо использования store.getState(), которое может вызвать несогласованность состояния, лучше использовать метод sample.

как работать с sample

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

  • При срабатывании clock прочитать значение из source
  • Если указан filter, и результат функции вернул true или стор со значением true, то продолжить
  • Если указан fn, то преобразовать данные
  • И передать данные в target.

Особенности работы sample

  • Если clock не передан, sample будет срабатывать при каждом обновлении source.
  • Если target не передан, то sample создаст и вернёт новый производный юнит

Возвращаемый юнит и значение

Если target не передан, то он будет создан при вызове. Тип создаваемого юнита описан в данной таблице:

clock \ sourceStoreEventEffect
StoreStoreEventEvent
EventEventEventEvent
EffectEventEventEvent

Использование таблицы:

  1. Выбираем тип источника clock, это столбец
  2. Тип source – это строка
  3. Устанавливаем соответствие между столбцом и строкой

В случае, если target передан явно, то возвращаемым значением будет тот же самый target.

Например:

const event = createEvent();
const $store = createStore();
const $secondStore = createStore();

const $derivedStore = sample({
  clock: $store,
  source: $secondStore,
});
// Результатом будет производный стор,
// так как `source` и `clock` являются сторами

const derivedEvent = sample({
  clock: event,
  source: $store,
});
// Результатом будет производное событие, так как `clock` – событие

Полная форма

  • Формула
sample({
  clock?, // триггер
  source?, // источник данных
  filter?, // фильтр
  fn?, // функция-трансформатор
  target?, // целевой юнит
  batch?, // флаг батчинга
  name? // имя sample юнита
})

clock

Аргумент clock является триггером, определяющий момент взятия данных из source.
Является опциональным.

  • Тип
sample({
  clock?: Unit<T> | Unit<T>[],
})

Может иметь сигнатуру:

  • Event<T> - срабатывает при вызове события
  • Store<T> - срабатывает при изменении стора
  • Effect<T, Done, Fail> - срабатывает при вызове эффекта
  • Unit<T>[]- массив юнитов срабатывает при активации любого из них
либо clock либо source

Хотя аргумент clock является опциональным, при использовании метода sample необходимо указать либо clock, либо source.

const clicked = createEvent();
const $store = createStore(0);
const fetchFx = createEffect();

// Event как clock
sample({
  source: $data,
  clock: clicked,
});

// Store как clock
sample({
  source: $data,
  clock: $store,
});

// Массив как clock
sample({
  source: $data,
  clock: [clicked, fetchFx.done],
});

source

Является источником данных, откуда берутся данные при срабатывании clock. Если clock не указан, тогда source используется как clock.
Является опциональным.

  • Тип
sample({
  source?: Unit<T> | Unit<T>[] | {[key: string]: Unit<T>},
})

Может иметь сигнатуру:

  • Store<T> - данные берутся из текущего значения стора
  • Event<T> - возьмется последнее значение, с которым запускалось событие
  • Effect<T, Done, Fail> - возьмется последнее значение, с которым запускался эффект
  • Объект с юнитами - для комбинирования нескольких источников
  • Массив с юнитами - для комбинирования нескольких источников
либо source либо clock

Хотя аргумент source является опциональным, при использовании метода sample необходимо указать либо source, либо clock.


filter

Функция-предикат для фильтрации. Если возвращает false или стор со значением false, данные не будут переданы в target.
Является опциональным.

  • Тип
sample({
  filter?: Store<boolean> | (source: Source, clock: Clock) => (boolean | Store<boolean>),
})

Может иметь сигнатуру:

  • Store<boolean> – стор с boolean значением, как производный так и базовый
  • Функция-предикат – функция возвращающая boolean значение
const $isUserActive = createStore(false);

sample({
  clock: checkScore,
  source: $score,
  filter: (score) => score > 100,
  target: showWinnerFx,
});

sample({
  clock: action,
  source: $user,
  filter: $isUserActive,
  target: adminActionFx,
});

fn

Функция для трансформации данных перед передачей в target. Функция должна быть чистой.
Является опциональным.

  • Тип
sample({
  fn?: (source: Source, clock: Clock) => Target
})
возвращаемый тип данных

Тип возвращаемых данных должен совпадать с типом данных в target.

const $user = createStore<User>({});
const saveUserFx = createEffect((user: User) => {
  // ...
});

sample({
  clock: updateProfile,
  source: $user,
  fn: (user, updates) => ({ ...user, ...updates }),
  target: saveUserFx,
});

sample({
  clock: submit,
  source: $form,
  fn: (form) => form.email,
  target: sendEmailFx,
});

target

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

  • Тип
sample({
  target?: Unit<T> | Unit<T>[],
})

Может иметь сигнатуру:

  • EventCallable<T> - событие (не производное) будет вызвано с данными
  • Effect<T, Done, Fail> - эффект будет вызван с данными
  • StoreWritable<T> - стор (не производный) будет обновлён данными
  • Массив с юнитами - будет вызван каждый юнит в массиве
target без target

Если target не указан, sample возвращает новый производный юнит.

const targetEvent = createEvent<string>();
const targetFx = createEffect<string, void>();
const $targetStore = createStore("");

// Event как target
sample({
  source: $store,
  clock: trigger,
  target: targetEvent,
});

// Effect как target
sample({
  source: $store,
  clock: trigger,
  target: targetFx,
});

// Store как target
sample({
  source: $store,
  clock: trigger,
  target: $targetStore,
});

greedy

Deprecated

Начиная с effector 23.0.0 свойство greedy устарело.

Используйте batch вместо greedy.


batch

Группирует обновления для лучшей производительности. По умолчанию true.
Является опциональным.

  • Тип
sample({
  batch?: boolean // По умолчанию true
})

name

Свойство name позволяет задать имя создаваемому юниту. Это имя используется для отладки.
Является опциональным.

  • Тип
sample({
  name?: string
})

Краткая форма

  • Формула
sample(source, clock, fn?): Unit

Альтернативная запись метода, всегда имеет неявный target.

Краткая форма также имеет несколько паттернов написания:

  1. Все аргументы: sample(source, clock, fn) - с функцией-трансформером
  2. source и clock: sample(source, clock) - без функции-трансформера
  3. source и fn: sample(source, fn) - с функцией-трансформером, но безclock, тогда sourceведет какclock
  4. Один аргумент: sample(source) - только source, тогда source ведет как clock
  • Возвращаемое значение

Возвращаемое значение зависит от переданных юнитов, а тип данных от fn, если присутствует, иначе от source.

source

Является источником данных, откуда берутся данные при срабатывании clock. Если clock не указан, тогда source используется как clock.

  • Тип
sample(source?: Unit<T> | Unit<T>[])

Может иметь сигнатуру:

  • Store<T> - данные берутся из текущего значения стора
  • Event<T> - возьмется последнее значение, с которым запускалось событие
  • Effect<T, Done, Fail> - возьмется последнее значение, с которым запускался эффект
  • Unit<T>[]- массив юнитов срабатывает при активации любого из них
поведение без clock

Если clock не указан, тогда source ведет себя как clock - то есть является триггером.


clock

Аргумент clock является триггером, определяющий момент взятия данных из source.
Является опциональным.

  • Тип
sample(clock?: Unit<T> | Unit<T>[])

Может иметь сигнатуру:

  • Event<T> - срабатывает при вызове события
  • Store<T> - срабатывает при изменении стора
  • Effect<T, Done, Fail> - срабатывает при вызове эффекта
  • Unit<T>[]- массив юнитов срабатывает при активации любого из них
const clicked = createEvent();
const $store = createStore(0);
const fetchFx = createEffect();

sample($data, clicked);

sample($data, $store);

fn

Функция для трансформации данных перед передачей в target. Функция должна быть чистой.
Является опциональным.

  • Тип
sample(fn: (source: Source, clock: Clock) => result)
  • Пример
const $userName = createStore("john");

const submitForm = createEvent();

const sampleUnit = sample(
  $userName /* 2 */,
  submitForm /* 1 */,
  (name, password) => ({ name, password }) /* 3 */,
);

submitForm(12345678);

// 1. при вызове submitForm с аргументом 12345678
// 2. прочитать значение из стора $userName ('john')
// 3. преобразовать значение из submitForm (1) и $userName (2) и вызвать sampleUnit
Перевод поддерживается сообществом

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

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

Соавторы