Перейти к основному содержимому

sample

Метод для связывания юнитов связью вида "при срабатывании clock прочитать значение из source и передать в target"

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

Формула#

sample({source?, clock?, fn?, target?}): target

При срабатывании clock прочитать значение из source и передать в target

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

Иллюстрация принципа работы#

Иллюстрация принципа работы

sample({clock?, source?, fn?, target?, greedy?})#

Основная запись метода

Аргументы

params (Object): Объект конфигурации

  • clock?: Юнит или массив юнитов

    Разновидности:

    • событие или эффект: срабатывание этого события/эффекта будет запускать target
    • стор: обновление этого стора будет запускать target
    • массив юнитов: срабатывание любого из юнитов будет запускать target. Сокращение для вызова merge
    • поле отсутствует: source будет использоваться в качестве clock
  • source?: Юнит или массив/объект со сторами

    Разновидности:

    • событие или эффект: при срабатывании clock будет взято последнее значение с которым запускался этот юнит (перед этим он должен будет запуститься хотя бы раз)
    • стор: при срабатывании clock будет взято текущее значение этого стора
    • массив или объект со сторами: при срабатывании clock будут взяты текущие значения из заданных сторов, объединенных в объект или массив. Сокращение для вызова combine
    • поле отсутствует: clock будет использоваться в качестве source
  • target?: Юнит или массив юнитов

    Разновидности:

    • событие или эффект: при срабатывании clock будет вызван данный юнит
    • стор: при срабатывании clock состояние юнита будет обновлено
    • массив юнитов: при срабатывании clock будут запущены все юниты
    • поле отсутствует: новый юнит будет создан и возвращен в результате вызова sample. Его тип зависит от типов clock и source
  • fn?: (sourceData, clockData) => result

    Функция-обработчик, которая будет преобразовывать данные из source и clock перед отправлением в target, должна быть чистой. В случае отсутствия этого поля, данные из source будут передаваться в target как есть

  • greedy?: boolean

    Модификатор, определяющий, будет ли target ожидать окончательного значения clock прежде чем запуститься самому. При greedy: false target будет срабатывать только раз после каждой серии идущих подряд обновлений, а при greedy: true, target сработает по разу при каждом триггере clock. Иными словами, эта опция отключает стабилизацию апдейтов clock и вынуждает обрабатывать все промежуточные значения. Батчинг обновлений повышает общую эффективность работы системы, поэтому по умолчанию greedy установлен в false

note

Поддержка массивов юнитов в target добавлена в effector 21.8.0

Возвращает

(Event | Store) - Юнит, который будет срабатывать при срабатывании clock, если target не передан. Тип возвращаемого юнита зависит от типов clock и source

Пример#

const $userName = createStore('john')
const signIn = createEffect(params => {
console.log(params)
})
const submitForm = createEvent()
sample({
clock: submitForm /* 1 */,
source: $userName /* 2 */,
fn: (name, password) => ({name, password}) /* 3 */,
target: signIn /* 4 */,
})
submitForm(12345678)
// 1. при вызове submitForm с аргументом 12345678
// 2. прочитать значение из стора $userName ('john')
// 3. преобразовать значение из submitForm (1) и $userName (2)
// 4. и передать результат вычислений в эффект signIn

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

sample(source, clock, fn?): Unit#

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

Аргументы

  • source: Юнит

    Разновидности:

    • событие или эффект: при срабатывании clock будет взято последнее значение с которым запускался этот юнит (перед этим он должен будет запуститься хотя бы раз)
    • стор: при срабатывании clock будет взято текущее значение этого стора
  • clock: Юнит

    Разновидности:

    • событие или эффект: срабатывание этого события/эффекта будет запускать target
    • стор: обновление этого стора будет запускать target
    • поле отсутствует: source будет использоваться в качестве clock
  • fn?: (sourceData, clockData) => result

    Функция-обработчик, которая будет преобразовывать данные из source и clock перед отправлением в target, должна быть чистой. В случае отсутствия этого поля, данные из source будут передаваться в target как есть. Поскольку этот обработчик призван организовывать поток данных, следует избегать объявления в нём сайд-эффектов. Правильнее будет поместить их в эффекты или в метод watch возвращаемого юнита

Возвращает

(Event | Store) - Юнит, который будет срабатывать при срабатывании clock, если target не передан. Тип возвращаемого юнита зависит от типов clock и source.

Пример#

const $userName = createStore('john')
const signIn = createEffect(params => {
console.log(params)
})
const submitForm = createEvent()
const sampleUnit = sample(
$userName /* 2 */,
submitForm /* 1 */,
(name, password) => ({name, password}) /* 3 */,
)
forward({
from: sampleUnit,
to: signIn /* 4 */,
})
submitForm(12345678)
// 1. при вызове submitForm с аргументом 12345678
// 2. прочитать значение из стора $userName ('john')
// 3. преобразовать значение из submitForm (1) и $userName (2)
// 4. и передать результат вычислений в эффект signIn

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

Объекты и массивы в source#

Объект со сторами#

note

Добавлено в effector 20.8.0

sample может быть вызван с объектом со сторами в source:

import {createStore, createEvent, sample} from 'effector'
const trigger = createEvent()
const a = createStore('A')
const b = createStore(1)
// target имеет тип `Event<{ a: string, b: number }>`
const target = sample({
clock: trigger,
source: {a, b},
})
target.watch(obj => {
console.log('sampled object', obj)
})
trigger()
// => sampled object {a: 'A', b: 1}

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

Массив сторов#

note

Добавлено в effector 20.8.0

sample может быть вызван с массивом сторов в source:

import {createStore, createEvent, sample} from 'effector'
const trigger = createEvent()
const a = createStore('A')
const b = createStore(1)
// target имеет тип `Event<[string, number]>`
const target = sample({
clock: trigger,
source: [a, b],
})
target.watch(obj => {
console.log('sampled array', obj)
})
// Можно деструктурировать аргументы, чтобы задать явные имена
target.watch(([a, b]) => {
console.log('explicit names', a, b)
})
trigger()
// => sampled array ["A", 1]
// => explicit names "A" 1

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

Массивы юнитов в clock#

note

Добавлено в effector 21.2.0

Передача массивов юнитов в clock работает как вызов merge

import {createStore, createEvent, createEffect, sample, merge} from 'effector'
const showNotification = createEvent<string>()
const trigger = createEvent()
const fx = createEffect()
const store = createStore('')
// массив юнитов в clock
sample({
clock: [trigger, fx.doneData],
source: store,
target: showNotification,
})
// объединённый юнит в clock
sample({
clock: merge([trigger, fx.doneData]),
source: store,
target: showNotification,
})

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

Тип создаваемого target#

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

clock\sourceStoreEventEffect
StoreStoreEventEvent
EventEventEventEvent
EffectEventEventEvent

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

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

Например:

const $store = sample({clock: $store, source: $store})
// Результатом будет стор, так как source и clock являются сторами
const event = sample({clock: event, source: $store})
// Результатом будет эвент, так как clock - не стор

Поле name#

note

Добавлено в effector 20.4.0

Любой юнит в эффекторе может иметь имя, поле name в sample позволяет указать имя создаваемому target

import {createStore, sample} from 'effector'
const foo = createStore(null)
const sampled = sample({
source: foo,
name: 'sampled foo',
})
console.log(sampled.shortName) // 'sampled foo'
Последнее обновление