События

События

Хотя в effector есть три основные концепции — события, сторы и эффекты, но именно события можно назвать основой для работы вашего приложения. Весь frontend построен поверх событийной модели, вы наверняка уже сталкивались с событиями при работе в JavaScript, например addEventListener или в React с onClick и другими обработчиками – это все события, на которые мы можем подписаться, так и в effector мы можем создать свое событие с помощью createEvent и подписаться на его вызов:

let counter = 10;
document.addEventListener("click", () => {
counter = 13;
});
import { createEvent, createStore, sample } from "effector";
const $counter = createStore(10);
const click = createEvent();
sample({
clock: click,
fn: () => 13,
target: $counter,
});
События effector

События в effector не то же самое, что события DOM, данный пример служит демонстрацией похожей концепции работы.

Зачем нужны события

Весь код на effector строится поверх событий, например если вы передадите стор в параметр clock у метода sample, то такой sample будет вызываться при срабатывании события updates у переданного стора:

// этот код эквивалентен
import { createStore, sample } from "effector";
const $someStore = createStore();
sample({
clock: $someStore,
// ...
});
// этот код эквивалентен
import { createStore, sample } from "effector";
const $someStore = createStore();
sample({
clock: $someStore.updates,
// ...
});

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

Для более простого понимания – событиями является все, с чем пользователь может взаимодействовать, а также внутренняя работы вашей логики. То есть помимо UI ориентированных событий по типу buttonClicked, inputChanged и прочее, у вас также могут быть и события завязанные на обновлении данных: valueUpdated или errorOccured.

Например у эффектов имеются встроенные событие done, которое срабатывает при успешном завершении работы эффекта, а также событие fail, если во время выполнения выбросилась ошибка. А сторы имеют событие updates, которое вызывается при его обновлении.

События также позволяют нам держать код слабо связным, что упрощает поддержку и тестирование.

Важность событий

На странице Как мыслить в парадигме effector мы подробно рассказываем о том, почему события важны, чем они еще полезны и какую пользу могут принести.

Как использовать события

Создать события мы можем с помощью метода createEvent, а далее подписываться на вызов этого события с помощью метода sample:

import { sample, createEvent } from "effector";
const event = createEvent();
sample({
clock: event,
// ...
});
Что такое sample

Если вы не знакомы с методом sample, то в примере с событиями он создает подписку на переданное событие в clock, а когда событие вызывается запускает цепочку выполнения. Более подробно вы познакомиться с логикой его работы на странице Композиция юнитов.

С помощью событий мы можем как обновлять сторы, так и вызывать эффекты или другие события:

import { sample, createStore, createEvent } from "effector";
const $clicksCount = createStore(0);
const userClicked = createEvent<void>();
// обновляем стор счетчик
sample({
clock: userClicked,
source: $clicksCount,
fn: (clicksCount) => count + 1,
target: $clicksCount,
});
userClicked();
import { createEvent, createEffect, sample } from "effector";
const startFetch = createEvent<string>();
const fetchFx = createEffect((url: string) => {
// ...
});
// вызываем эффект
sample({
clock: startFetch,
target: fetchFx,
});
startFetch("/fake-api/users");

Важная особенность событий, что они могут принимать только один аргумент, остальные будут проигнорированы. Если вам необходимо передать несколько аргументов, то используйте объект:

const event = createEvent<{ a: number; b: string }>();
event({
a: 1,
b: "string",
});

Вызов события

Вызвать событие можно двумя путями: императивно и декларативно.

Императивным способ вызова это наиболее привычный, когда мы вызываем событие как функцию event(), такой способ, скорее всего, вы будете использовать при вызове события в UI, когда передаете в onClick, onChange обработчики и другие:

import { createEvent } from "effector";
// можно использовать любой другой фреймворк и пакет с его интеграцией
import { useUnit } from "effector-react";
const clickHappened = createEvent<void>();
// view.tsx
import { useUnit } from "effector-react";
const Component = () => {
const click = useUnit(clickHappened);
return (
<div>
<button onClick={() => click()}>click</button>
</div>
);
};
события и фреймворки

Заметьте, чтобы вызвать событие в UI при работе с фреймворком, вам нужно использовать хук useUnit.

Декларативный вызов это, например, когда мы подписываемся событием на другое событие с помощью метода sample и аргумента target. Событие переданное в target вызовется при срабатывании clock:

import { createEvent, sample } from "effector";
const firstTriggered = createEvent<void>();
const secondTriggered = createEvent<void>();
sample({
clock: firstTriggered,
target: secondTriggered,
});
А можно ли вызывать императивно в sample?

Декларативыный способ вызова события это единственный правильный способ при работе с sample. Однако вы можете вызывать императивно с помощью метода createAction или в теле эффекта.

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

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

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

Соавторы