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

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

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

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

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

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

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

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

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

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

Методы стора

.map(fn)

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

Формула

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

Аргументы

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

Возвращает

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

Примеры

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

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: Текущий стор.

Примеры

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

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 каждый раз, когда стор обновляется.

Формула

const unwatch = $store.watch(watcher);

Аргументы

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

Возвращает

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.reset(...triggers);

Аргументы

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

Возвращает

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: Текущий стор.

Примеры

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

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);

Попробовать

Свойства стора

.updates

Возвращает

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

Пример

import { createStore, is } from "effector";

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

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

Попробовать

.reinit

Возвращает

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

Пример

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()

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

Возвращает

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

Пример

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());

Попробовать

Стор только для чтения

TBD

Типы

import { type StoreValue } from "effector";

StoreValue<S>

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

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

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

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

Соавторы