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

Event

Event (событие, эвент) это декларация намерения сделать что-либо: запустить вычисления, отправить сообщение другой секции приложения или обновить состояния в приложении. Одна из основных управляющих сущностей, при срабатывании запускает цепочки реактивных вычислений в приложении. Является юнитом

События можно вызывать как обычные функции (императивный вызов) а также подключать в различные методы api включая sample, guard и split (декларативное подключение). При императивном вызове принимают максимум один аргумент и всегда возвращают переданные данные

Структура#

  • Методы

    • map: создает производное событие на основе данных из исходного
    • prepend: создает событие-триггер для преобразования данных перед запуском исходного эвента
    • filterMap: создает производное событие на основе данных из исходного с возможностью отмены вызова
    • watch: вызывает функцию с сайд-эффектами при каждом срабатывании события
  • Свойства

    • shortName: имя события
    • sid: стабильный идентификатор события

Примеры#

Методы#

map#

Создает производное событие на основе данных из исходного

Формула#

declare const eventA: Event<T>
const eventB = eventA.map(/*fn*/(data: T) => S)
-> Event<S>

При вызове исходного события eventA, функция-обработчик fn будет вызвана с поступившими данными, после чего производный эвент eventB будет вызван с результатом вычислений

eventA -> fn -> eventB

Аргументы#

  1. fn: (data: T) => S

    Функция-обработчик, которая будет вычислять данные для передачи в производное событие eventB на основе данных из исходного эвента eventA. Должна быть чистой

    Аргументы

    • data: Данные с которыми сработало исходное событие eventA

    Возвращает

    Данные для передачи в производное событие eventB

Возвращает#

Новое, производное событие

Примеры#

Пример использования map#
import {createEvent} from 'effector'
const updateUser = createEvent()
const userNameUpdated = updateUser.map(({name}) => name)
const userRoleUpdated = updateUser.map(({role}) => role.toUpperCase())
userNameUpdated.watch(name =>
console.log(`Имя пользователя изменено на ${name}`),
)
userRoleUpdated.watch(role =>
console.log(`Роль пользователя изменена на ${role}`),
)
updateUser({name: 'john', role: 'admin'})
// => Имя пользователя изменено на john
// => Роль пользователя изменена на ADMIN

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

prepend#

Создаёт событие-триггер для преобразования данных перед запуском исходного эвента. По сравнению с map, работает в обратном направлении

Формула#

declare const targetEvent: Event<S>
const trigger = targetEvent.prepend(/*fn*/(data: T) => S)
-> Event<T>

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

trigger -> fn -> targetEvent

Аргументы#

  1. fn: (data: T) => S

    Функция-обработчик, которая будет вычислять данные для передачи в исходное событие targetEvent на основе данных эвента trigger. Должна быть чистой

    Аргументы

    • data: Данные с которыми сработало событие trigger

    Возвращает

    Данные для передачи в исходное событие targetEvent

Возвращает#

Новое событие

Примеры#

Пример использования prepend#
import {createEvent} from 'effector'
const userPropertyChanged = createEvent()
userPropertyChanged.watch(({field, value}) => {
console.log(`Свойство пользователя "${field}" изменено на ${value}`)
})
const changeName = userPropertyChanged.prepend(name => ({
field: 'name',
value: name,
}))
const changeRole = userPropertyChanged.prepend(role => ({
field: 'role',
value: role.toUpperCase(),
}))
changeName('john')
// => Свойство пользователя "name" изменено на john
changeRole('admin')
// => Свойство пользователя "role" изменено на ADMIN
changeName('alice')
// => Свойство пользователя "name" изменено на alice

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

filterMap#

Создает производное событие на основе данных из исходного с возможностью отмены вызова

note

Метод добавлен в effector 20.0.0

Формула#

declare const eventA: Event<T>
const eventB = eventA.filterMap(
/*fn*/ (data: T) => S | void
)
-> Event<S>

При вызове исходного события eventA, функция-обработчик fn будет вызвана с поступившими данными, после чего, если функция вернула не undefined, производный эвент eventB будет вызван с результатом вычислений

eventA -> fn -> eventB
note

Если требуется только фильтрация вызовов без трансформации данных, то оптимальнее использовать guard

Аргументы#

  1. fn: (data: T) => S | void

    Функция-обработчик, которая будет вычислять данные для передачи в производное событие eventB на основе данных из исходного эвента eventA. Должна быть чистой

    Аргументы

    • data: Данные с которыми сработало исходное событие eventA

    Возвращает

    Данные для передачи в производное событие eventB либо undefined, если вызов eventB не требуется

Возвращает#

Новое, производное событие

Примеры#

Использование nullable react ref с filterMap#
note

Методы modal.showModal и modal.close - стандартные возможности dom-элемента <dialog>

Статья в MDN про showModal

import React from 'react'
import {createEvent, createStore} from 'effector'
const openModal = createEvent()
const closeModal = createEvent()
const openModalUnboxed = openModal.filterMap(ref => {
if (ref.current) return ref.current
})
const closeModalUnboxed = closeModal.filterMap(ref => {
if (ref.current) return ref.current
})
openModalUnboxed.watch(modal => modal.showModal())
closeModalUnboxed.watch(modal => modal.close())
const App = () => {
const modalRef = React.useRef(null)
return (
<>
<dialog ref={modalRef}>
<form method="dialog">
<fieldset>
<legend>Модальное окно</legend>
Нажмите для закрытия
<button onSubmit={() => closeModal(modalRef)} type="submit">
</button>
</fieldset>
</form>
</dialog>
<button onClick={() => openModal(modalRef)}>
Открыть модальное окно
</button>
</>
)
}

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

watch#

Вызывает функцию с сайд-эффектами при каждом срабатывании события

note

По мере усложнения логики проекта оптимальнее заменить на комбинацию эффекта и сэмпла

Формула#

declare const event: Event<T>
event.watch(/*watcher*/ (data: T) => any)
-> Subscription

Аргументы#

  1. watcher: (data: T) => any

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

Возвращает#

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

Примеры#

Пример использования watch#
import {createEvent} from 'effector'
const sayHi = createEvent()
const stop = sayHi.watch(name => {
console.log(`Привет, ${name}!`)
})
sayHi('Боб')
// => Привет, Боб!
stop()
sayHi('Алиса')
// => ничего не произошло

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


Свойства#

shortName#

Имя события. Задаётся либо явно, через поле name в createEvent, либо автоматически через babel plugin. Используется для обработки сущностей программно, например при использовании хуков домена

Формула#

declare const event: Event<any>
event.shortName
-> string

sid#

Стабильный идентификатор события. Задаётся автоматически через babel-plugin

Формула#

declare const event: Event<any>
event.sid
-> string | null

Дополнительные методы#

filter#

Создает производное событие с возможностью отмены вызова

note

Более гибким способом фильтрации является guard, рекомендуется использовать именно его

Формула#

declare const eventA: Event<T>
const eventB = eventA.filter(/*config*/ {fn: (data: T) => boolean})
-> Event<T>

При вызове исходного события eventA, функция-обработчик fn будет вызвана с поступившими данными, после чего, если функция вернула истинное значение, производный эвент eventB будет вызван с теми же данными

Аргументы#

  1. config: Объект конфигурации

Возвращает#

Новое, производное событие

note

Объектная форма аргумента используется потому что event.filter(fn) был сокращённой формой filterMap

Примеры#

Пример использования filter#
import {createEvent, createStore} from 'effector'
const numbers = createEvent()
const positiveNumbers = numbers.filter({
fn: ({x}) => x > 0,
})
const $lastPositive = createStore(0).on(positiveNumbers, (n, {x}) => x)
$lastPositive.watch(x => {
console.log('последнее положительное значение:', x)
})
// => последнее положительное значение: 0
numbers({x: 0})
// ничего не произошло
numbers({x: -10})
// ничего не произошло
numbers({x: 10})
// => последнее положительное значение: 10

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

Последнее обновление