import { type Store, type StoreWritable } from "effector";

Store — это объект, который хранит значение состояния. Store обновляется, когда получает значение, которое не равно (!==) текущему и не равно undefined. Store является Unit. Некоторые stores могут быть derived.

Иммутабельность

Store в effector иммутабелен. Это значит, что обновления в нём будут происходить только если в функции-обработчике (например combine, sample или on) вернуть новый объект

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

$items.on(addItem, (items, newItem) => {
  const updatedItems = [...items];
  // ✅ метод .push вызывается на новом массиве
  updatedItems.push(newItem);
  return updatedItems;
});

Так делать нельзя, обновления стора не произойдёт

$items.on(addItem, (items, newItem) => {
  // ❌ ошибка! Ссылка на массив осталась та же, обновления store не произойдёт
  items.push(newItem);
  return items;
});

Обновление объектов происходит аналогичным образом

Store в effector должен быть размером как можно меньше, чтобы отвечать за конкретную часть в бизнес логике, в отличии от например redux, store которого имеет тенденцию к тому чтобы держать рядом всё и сразу. Когда состояние атомарное, то необходимости в спредах объектов становится меньше. Однако, если возникает потребность часто обновлять сильно вложенные данные, для обновления состояния допустимо применять immer чтобы упростить повторяющийся код

Методы Store

.map(fn)

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

Формула

const $second = $first.map(fn);

Аргументы

  1. fn (Function): Функция, которая принимает state и возвращает новое состояние для производного store.
  2. config (Object): Необязательная конфигурация.

Возвращает

DerivedStore: Новый производный store.

Примеры

Основной пример

import { createEvent, createStore } from "effector";

const changed = createEvent();
const $title = createStore("").on(changed, (_, newTitle) => newTitle);
const $length = $title.map((title) => title.length);

$length.watch((length) => {
  console.log("new length", length);
});

changed("hello");
changed("world");
changed("hello world");

Попробовать

Пропускать пустые значения

const $length = $title.map((title) => title.length, { skipVoid: false });

.on(trigger, reducer)

Обновляет состояние, когда trigger срабатывает, используя reducer.

Формула

$store.on(trigger, reducer);

Аргументы

  1. trigger: Event, Effect или другой Store.
  2. reducer: Reducer: Функция, которая принимает state и params и возвращает новое состояние.

Возвращает

Store: Текущий store.

Примеры

Основной пример

import { createEvent, createStore } from "effector";

const $store = createStore(0);
const changed = createEvent();

$store.on(changed, (value, incrementor) => value + incrementor);

$store.watch((value) => {
  console.log("updated", value);
});

changed(2);
changed(2);

Попробовать

.watch(watcher)

Вызывает функцию watcher каждый раз, когда store обновляется.

Формула

const unwatch = $store.watch(watcher);

Аргументы

  1. watcher: Watcher: Функция-наблюдатель, которая принимает текущее состояние store в качестве первого аргумента.

Возвращает

Subscription: Функция для отмены подписки.

Примеры

Основной пример

import { createEvent, createStore } from "effector";

const add = createEvent();
const $store = createStore(0).on(add, (state, payload) => state + payload);

$store.watch((value) => console.log(`current value: ${value}`));
add(4);
add(3);

Попробовать

.reset(...triggers)

Сбрасывает состояние store до значения по умолчанию.

Формула

$store.reset(...triggers);

Аргументы

  1. triggers: ((Event | Effect | Store)[]): любое количество Events, Effects или Stores.

Возвращает

Store: Текущий store.

Примеры

Основной пример

import { createEvent, createStore } from "effector";

const increment = createEvent();
const reset = createEvent();

const $store = createStore(0)
  .on(increment, (state) => state + 1)
  .reset(reset);

$store.watch((state) => console.log("changed", state));

increment();
increment();
reset();

Попробовать

.off(trigger)

Удаляет reducer для указанного trigger.

Формула

$store.off(trigger);

Аргументы

  1. trigger: Event, Effect или Store.

Возвращает

Store: Текущий store.

Примеры

Основной пример

import { createEvent, createStore, merge } from "effector";

const changedA = createEvent();
const changedB = createEvent();

const $store = createStore(0);
const changed = merge([changedA, changedB]);

$store.on(changed, (state, params) => state + params);
$store.off(changed);

Попробовать

Свойства Store

.updates

Возвращает

Event: Событие, представляющее обновления данного store.

Пример

import { createStore, is } from "effector";

const $clicksAmount = createStore(0);
is.event($clicksAmount.updates); // true

$clicksAmount.updates.watch((amount) => {
  console.log(amount);
});

Попробовать

.reinit

Возвращает

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

Пример

import { createStore, createEvent, sample, is } from "effector";

const $counter = createStore(0);
is.event($counter.reinit);

const increment = createEvent();

$counter.reinit();
console.log($counter.getState());

Попробовать

.shortName

Возвращает

(string): ID или короткое имя store.

.defaultState

Возвращает

(State): Значение состояния по умолчанию.

Пример

const $store = createStore("DEFAULT");
console.log($store.defaultState === "DEFAULT");

Вспомогательные методы

.getState()

Возвращает текущее состояние store.

Возвращает

(State): Текущее состояние store.

Пример

import { createEvent, createStore } from "effector";

const add = createEvent();

const $number = createStore(0).on(add, (state, data) => state + data);

add(2);
add(3);

console.log($number.getState());

Попробовать

Только для чтения store

TBD

Типы

import { type StoreValue } from "effector";

StoreValue<S>

Извлекает тип значения Store или StoreWritable.

const $store: Store<Value>;
type Value = StoreValue<typeof $store>;
Перевод поддерживается сообществом

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

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

Соавторы