combine API
import { combine } from "effector";Метод combine позволяет получить состояние из каждого переданного стора и комбинировать их в одно значение, сохраняя его в новом производном сторе. Полученный стор будет обновляться каждый раз, когда обновляется любой из переданных сторов.
Алгоритм
combineчитает текущее состояние из всех переданных сторов.- Если предоставлена функция трансформации
fn, она вызывается со значениями из сторов. - Результат сохраняется в новом производном сторе.
- Производный стор обновляется при каждом изменении любого из исходных сторов.
Особенности
- Батчинг обновлений: Когда несколько сторов обновляются одновременно (за один тик),
combineобрабатывает их все сразу, что приводит к единственному обновлению производного стора. - Смешивание сторов с примитивами: В
combineможно передавать не только сторы, но и примитивы и объекты. Effector не будет отслеживать мутации этих примитивов и объектов - они рассматриваются как статические значения. - Чистые функции трансформации: Все функции трансформации, передаваемые в
combine, должны быть чистыми. - Проверка строгого равенства: Если функция трансформации возвращает то же значение, что и предыдущее (сравнение через
!==), производный стор не обновится. - Обработка ошибок: Если функция трансформации выбрасывает ошибку во время выполнения, приложение завершится сбоем. Это будет исправлено в effector v24.
Формы конфигурации
Форма | Описание |
|---|---|
combine($a, fn) | Трансформирует значение одного стора через fn. |
combine(...$stores, fn?) | Комбинирует несколько сторов/значений, опционально трансформируя через fn. |
combine({ a: $a, b: $b }, fn?) | Комбинирует сторы в объект-стор, опционально трансформируя через fn. |
combine([$a, $b], fn?) | Комбинирует сторы в массив-стор, опционально трансформируя через fn. |
Конфигурации
combine($store, fn)
Создает новый производный стор путем трансформации значения одного стора. Это предпочтительный метод для создания производных сторов с одним источником. Является альтернативным способом для Store.map().
- Формула
const $result = combine($source, (value) => { // логика трансформации return result;});- Тип
export function combine<A, R>( a: Store<A>, fn: (a: A) => R, config?: { skipVoid?: boolean; },): Store<R>;-
Особенности
- Функция трансформации
fnдолжна быть чистой. - Если
fnвозвращает то же значение, что и предыдущее (сравнение через!==), стор не обновится. - Если
fnвыбрасывает ошибку во время выполнения, приложение завершится сбоем (это будет исправлено в effector v24). - Опциональный параметр
config: см. конфигурациюcreateStoreдля деталей оskipVoid.
- Функция трансформации
-
Примеры
import { createStore, combine } from "effector";
const $name = createStore("John");const $greeting = combine($name, (name) => `Hello, ${name}!`);
$greeting.watch((greeting) => console.log(greeting));// => Hello, John!import { createStore, combine } from "effector";
const $price = createStore(100);const $priceWithTax = combine($price, (price) => price * 1.2);
$priceWithTax.watch((price) => console.log("Price with tax:", price));// => Price with tax: 120- Возвращает
Новый производный стор.
combine(...$stores, fn?)
Создает новый производный стор, который комбинирует любое количество сторов и значений. Принимает любое количество аргументов - сторы, примитивы или объекты. Последний аргумент может опционально быть функцией трансформации.
Без fn оборачивает все значения в массив. С fn трансформирует значения с помощью функции, где сторы передаются как отдельные аргументы.
- Формула
// без функции трансформацииconst $result = combine($a);const $result = combine($a, $b, $c);
// с функцией трансформацииconst $result = combine($a, (value) => { // логика трансформации return result;});
const $result = combine($a, $b, $c, (a, b, c) => { // логика трансформации return result;});- Тип
export function combine<T extends any[]>( ...stores: T): Store<{ [K in keyof T]: T[K] extends Store<infer U> ? U : T[K] }>;
export function combine<T extends any[], R extends any>( ...stores: T, fn: (...stores: [K in keyof T]: T[K] extends Store<infer U> ? U : T[K]) => R, config?: { skipVoid?: boolean },): Store<R>;
// также поддерживает любое количество сторов с опциональной fn в качестве последнего аргумента-
Особенности
- Принимает любое количество сторов, примитивов или объектов в качестве аргументов.
- Можно смешивать сторы со значениями как примитивы или объекты.
- Без
fnвозвращает массив-стор со значениями в том же порядке, что и аргументы. - Когда предоставлена
fn:- Функция трансформации
fnдолжна быть чистой. - Если
fnвозвращает то же значение, что и предыдущее (сравнение через!==), стор не обновится. - Если
fnвыбрасывает ошибку во время выполнения, приложение завершится сбоем (это будет исправлено в effector v24). - Опциональный параметр
config: см. конфигурациюcreateStoreдля деталей оskipVoid.
- Функция трансформации
-
Примеры
Без функции трансформации - создает массив-стор:
import { createStore, combine } from "effector";
const $firstName = createStore("John");const $lastName = createStore("Doe");const $age = createStore(30);
const $userData = combine($firstName, $lastName, $age);
$userData.watch((data) => console.log(data));// => ["John", "Doe", 30]С функцией трансформации - трансформирует комбинированные значения:
import { createStore, combine } from "effector";
const $firstName = createStore("John");const $lastName = createStore("Doe");
const $fullName = combine($firstName, $lastName, (first, last) => { return `${first} ${last}`;});
$fullName.watch((name) => console.log(name));// => "John Doe"Комбинирование нескольких сторов с трансформацией:
import { createStore, combine } from "effector";
const $price = createStore(100);const $quantity = createStore(2);const $discount = createStore(0.1);
const $total = combine($price, $quantity, $discount, (price, qty, disc) => { const subtotal = price * qty; return subtotal - subtotal * disc;});
$total.watch((total) => console.log(`Total: $${total}`));// => Total: $180Смешивание сторов с примитивами:
import { createStore, combine } from "effector";
const $userName = createStore("Alice");const API_URL = "https://api.example.com";
const $userEndpoint = combine($userName, API_URL, (name, url) => { return `${url}/users/${name}`;});
$userEndpoint.watch((endpoint) => console.log(endpoint));// => https://api.example.com/users/Alice- Возвращает
Новый производный стор.
combine({ a: $a, b: $b }, fn?)
Создает новый производный стор, который комбинирует объект сторов. Без fn создает объект-стор со значениями из переданных сторов. С fn трансформирует комбинированные значения с помощью функции.
- Формула
// без функции трансформацииconst $result = combine({ a: $a, b: $b, // ... больше сторов});
// с функцией трансформацииconst $result = combine({ a: $a, b: $b, c: $c }, ({ a, b, c }) => { // логика трансформации return result;});- Тип
export function combine<State, R>( shape: State, fn?: (shape: { [K in keyof State]: State[K] extends Store<infer U> ? U : State[K] }) => R, config?: { skipVoid?: boolean; },): Store<R>;-
Особенности
- Обновления батчатся, когда несколько сторов изменяются одновременно.
- Можно смешивать сторы со значениями как примитивы или объекты.
- если предоставлена
fn:- Функция трансформации
fnдолжна быть чистой. - Если
fnвозвращает то же значение, что и предыдущее (сравнение через!==), стор не обновится. - Если
fnвыбрасывает ошибку во время выполнения, приложение завершится сбоем (это будет исправлено в effector v24). - Опциональный параметр
config: см. конфигурациюcreateStoreдля деталей оskipVoid.
- Функция трансформации
-
Примеры
Без функции трансформации - создает объект-стор:
import { createStore, combine } from "effector";
const $firstName = createStore("John");const $lastName = createStore("Doe");const $age = createStore(30);
const $user = combine({ firstName: $firstName, lastName: $lastName, age: $age,});
$user.watch((user) => console.log(user));// => { firstName: "John", lastName: "Doe", age: 30 }С функцией трансформации - трансформирует значения объекта:
import { createStore, combine } from "effector";
const $firstName = createStore("John");const $lastName = createStore("Doe");const $age = createStore(30);
const $userSummary = combine( { firstName: $firstName, lastName: $lastName, age: $age }, ({ firstName, lastName, age }) => { return `${firstName} ${lastName}, ${age} years old`; },);
$userSummary.watch((summary) => console.log(summary));// => "John Doe, 30 years old"Практический пример - валидация формы:
import { createStore, combine } from "effector";
const $email = createStore("");const $password = createStore("");const $confirmPassword = createStore("");
const $formValidation = combine( { email: $email, password: $password, confirmPassword: $confirmPassword }, ({ email, password, confirmPassword }) => { const errors = [];
if (!email.includes("@")) { errors.push("Invalid email"); }
if (password.length < 8) { errors.push("Password must be at least 8 characters"); }
if (password !== confirmPassword) { errors.push("Passwords don't match"); }
return { isValid: errors.length === 0, errors, }; },);Смешивание сторов с примитивами и объектами:
import { createStore, combine } from "effector";
const $userId = createStore(123);const $isActive = createStore(true);
const $userData = combine({ id: $userId, isActive: $isActive, role: "user", permissions: ["read", "write"],});
$userData.watch((data) => console.log(data));// => { id: 123, isActive: true, role: "user", permissions: ["read", "write"] }- Возвращает
Новый производный стор.
combine([$a, $b], fn?)
Создает новый производный стор, который комбинирует массив сторов. Без fn создает массив-стор со значениями из переданных сторов в том же порядке. С fn трансформирует комбинированные значения с помощью функции.
- Формула
// без функции трансформацииconst $result = combine([$a, $b, $c]);
// с функцией трансформацииconst $result = combine([$a, $b, $c], ([a, b, c]) => { // логика трансформации return result;});- Тип
export function combine<State extends any[]>( tuple: State,): Store<{ [K in keyof State]: State[K] extends Store<infer U> ? U : State[K] }>;
export function combine<State extends any[], R>( tuple: State, fn: (tuple: { [K in keyof State]: State[K] extends Store<infer U> ? U : State[K] }) => R, config?: { skipVoid?: boolean },): Store<R>;-
Особенности
- Порядок массива совпадает с порядком переданных сторов.
- Обновления батчатся, когда несколько сторов изменяются одновременно.
- Можно смешивать сторы с не-сторовыми значениями, такими как примитивы или объекты.
- Когда предоставлена
fn:- Функция трансформации
fnдолжна быть чистой. - Функция получает массив, в котором порядок совпадает с порядком входного массива.
- Если
fnвозвращает то же значение, что и предыдущее (сравнение через!==), стор не обновится. - Если
fnвыбрасывает ошибку во время выполнения, приложение завершится сбоем (это будет исправлено в effector v24). - Опциональный параметр
config: см. конфигурациюcreateStoreдля деталей оskipVoid.
- Функция трансформации
-
Примеры
Без функции трансформации - создает массив-стор:
import { createStore, combine } from "effector";
const $x = createStore(10);const $y = createStore(20);const $z = createStore(30);
const $coordinates = combine([$x, $y, $z]);
$coordinates.watch((coords) => console.log(coords));// => [10, 20, 30]С функцией трансформации - трансформирует значения массива:
import { createStore, combine } from "effector";
const $x = createStore(3);const $y = createStore(4);
const $distance = combine([$x, $y], ([x, y]) => { return Math.sqrt(x * x + y * y);});
$distance.watch((dist) => console.log(`Distance: ${dist}`));// => Distance: 5Практический пример - вычисление итогов из массива:
import { createStore, combine } from "effector";
const $itemPrice1 = createStore(10);const $itemPrice2 = createStore(25);const $itemPrice3 = createStore(15);
const $cartTotal = combine([$itemPrice1, $itemPrice2, $itemPrice3], (prices) => { return prices.reduce((sum, price) => sum + price, 0);});
$cartTotal.watch((total) => console.log(`Total: $${total}`));// => Total: $50Массив с разными типами:
import { createStore, combine } from "effector";
const $userName = createStore("Alice");const $score = createStore(100);const $isActive = createStore(true);
const $playerInfo = combine([$userName, $score, $isActive], ([name, score, active]) => { return `Player ${name}: ${score} points (${active ? "online" : "offline"})`;});
$playerInfo.watch((info) => console.log(info));// => Player Alice: 100 points (online)Смешивание сторов с примитивами в массиве:
import { createStore, combine } from "effector";
const $currentPage = createStore(1);const MAX_PAGES = 10;
const $pagination = combine([$currentPage, MAX_PAGES], ([current, max]) => { return { current, max, hasNext: current < max, hasPrev: current > 1, };});
$pagination.watch((pagination) => console.log(pagination));// => { current: 1, max: 10, hasNext: true, hasPrev: false }- Возвращает
Новый производный стор.
Связанное API и статьи
- API
Store API- Описание сторов, их методов и свойствcreateStore- Создание нового стораsample- Ключевой оператор для построения связей между юнитамиcreateEvent- Создание события
- Статьи
Документация на английском языке - самая актуальная, поскольку её пишет и обновляет команда effector. Перевод документации на другие языки осуществляется сообществом по мере наличия сил и желания.
Помните, что переведенные статьи могут быть неактуальными, поэтому для получения наиболее точной и актуальной информации рекомендуем использовать оригинальную англоязычную версию документации.