import { split } from "effector";

Выберите один из кейсов по заданным условиям. Эта функция “разделяет” исходный юнит на несколько событий, которые срабатывают, когда полезная нагрузка соответствует их условиям. Работает как сопоставление с образцом для значений полезной нагрузки и внешних сторов.

Режимы

“Case” режим

Режим, в котором кейс выбирается его имени. Кейс может быть выбран из данных в source с помощью функции кейса или из внешнего стора кейса, которое хранит текущее имя кейса. После выбора данные из source будут отправлены в соответствующий cases[fieldName] (если он есть), если ни одно из полей не совпадает, то данные будут отправлены в cases.__ (если он есть).

Смотрите также:

Режим сопоставления

Режим, в котором каждый кейс последовательно сопоставляется с сторами и функциями в полях объекта match. Если одно из полей получает true из значения стора или возврата функции, то данные из source будут отправлены в соответствующий cases[fieldName] (если он есть), если ни одно из полей не совпадает, то данные будут отправлены в cases.__ (если он есть).

Смотрите также:

Стор кейса

Store со строкой, который будет использоваться для выбора итогового кейса по его имени. Размещается непосредственно в поле match.

split({
  source: Unit<T>
  // стор кейса
  match: Store<'first' | 'second'>,
  cases: {
    first: Unit<T> | Unit<T>[],
    second: Unit<T> | Unit<T>[],
    __?: Unit<T> | Unit<T>[]
  }
})

Функция кейса

Функция, возвращающая строку, которая будет вызвана со значением из source для выбора итогового кейса по его имени. Размещается непосредственно в поле match, должна быть чистой.

split({
  source: Unit<T>
  // функция кейса
  match: (value: T) => 'first' | 'second',
  cases: {
    first: Unit<T> | Unit<T>[],
    second: Unit<T> | Unit<T>[],
    __?: Unit<T> | Unit<T>[]
  }
})

Стор сопоставления

Boolean store, который указывает, следует ли выбрать конкретный кейс или попробовать следующий. Размещается в полях объекта match, может быть смешано с функциями сопоставления.

split({
  source: Unit<T>
  match: {
    // стор сопоставления
    first: Store<boolean>,
    second: Store<boolean>
  },
  cases: {
    first: Unit<T> | Unit<T>[],
    second: Unit<T> | Unit<T>[],
    __?: Unit<T> | Unit<T>[]
  }
})

Функция сопоставления

Обратите внимание

Стор кейса, функция кейса и стор сопоставления поддерживаются с effector 21.8.0

Функция, возвращающая boolean значение, которое указывает, следует ли выбрать конкретный кейс или попробовать следующий. Размещается в полях объекта match, может быть смешано с store сопоставления, должна быть чистой.

split({
  source: Unit<T>
  match: {
    // функция сопоставления
    first: (value: T) => boolean,
    second: (value: T) => boolean
  },
  cases: {
    first: Unit<T> | Unit<T>[],
    second: Unit<T> | Unit<T>[],
    __?: Unit<T> | Unit<T>[]
  }
})

Методы

split({ source, match, cases })

Начиная с

Формула

split({ source, match, cases });
split({
  source: Unit<T>
  // функция кейса
  match: (data: T) => 'a' | 'b',
  cases: {
    a: Unit<T> | Unit<T>[],
    b: Unit<T> | Unit<T>[],
    __?: Unit<T> | Unit<T>[]
  }
})
split({
  source: Unit<T>
  // стор кейса
  match: Store<'a' | 'b'>,
  cases: {
    a: Unit<T> | Unit<T>[],
    b: Unit<T> | Unit<T>[],
    __?: Unit<T> | Unit<T>[]
  }
})
split({
  source: Unit<T>
  match: {
    // функция сопоставления
    a: (data: T) => boolean,
    // стор сопоставления
    b: Store<boolean>
  },
  cases: {
    a: Unit<T> | Unit<T>[],
    b: Unit<T> | Unit<T>[],
    __?: Unit<T> | Unit<T>[]
  }
})

Аргументы

Возвращает

void

Примеры

Базовый

import { split, createEffect, createEvent } from "effector";
const messageReceived = createEvent();
const showTextPopup = createEvent();
const playAudio = createEvent();
const reportUnknownMessageTypeFx = createEffect(({ type }) => {
  console.log("неизвестное сообщение:", type);
});

split({
  source: messageReceived,
  match: {
    text: (msg) => msg.type === "text",
    audio: (msg) => msg.type === "audio",
  },
  cases: {
    text: showTextPopup,
    audio: playAudio,
    __: reportUnknownMessageTypeFx,
  },
});

showTextPopup.watch(({ value }) => {
  console.log("новое сообщение:", value);
});

messageReceived({
  type: "text",
  value: "Привет",
});
// => новое сообщение: Привет
messageReceived({
  type: "image",
  imageUrl: "...",
});
// => неизвестное сообщение: image

Попробуйте

Прямое сопоставление

Вы также можете сопоставлять напрямую с API хранилища:

import { split, createStore, createEvent, createApi } from "effector";

const messageReceived = createEvent();

const $textContent = createStore([]);

split({
  source: messageReceived,
  match: {
    text: (msg) => msg.type === "text",
    audio: (msg) => msg.type === "audio",
  },
  cases: createApi($textContent, {
    text: (list, { value }) => [...list, value],
    audio: (list, { duration }) => [...list, `аудио ${duration} мс`],
    __: (list) => [...list, "неизвестное сообщение"],
  }),
});

$textContent.watch((messages) => {
  console.log(messages);
});

messageReceived({
  type: "text",
  value: "Привет",
});
// => ['Привет']
messageReceived({
  type: "image",
  imageUrl: "...",
});
// => ['Привет', 'неизвестное сообщение']
messageReceived({
  type: "audio",
  duration: 500,
});
// => ['Привет', 'неизвестное сообщение', 'аудио 500 мс']

Попробуйте

Кейс с массивами юнитов

import { createEffect, createEvent, createStore, sample, split } from "effector";

const $verificationCode = createStore("12345");
const $error = createStore("");

const modalToInputUsername = createEvent();
const modalToAuthorizationMethod = createEvent();

const checkVerificationCodeFx = createEffect((code) => {
  throw "500";
});

sample({
  clock: verificationCodeSubmitted,
  source: $verificationCode,
  target: checkVerificationCodeFx,
});

split({
  source: checkVerificationCodeFx.failData,
  match: (value) => (["400", "410"].includes(value) ? "verificationCodeError" : "serverError"),
  cases: {
    verificationCodeError: $verificationCodeError,
    serverError: [$error, modalToAuthorizationMethod],
  },
});

$error.updates.watch((value) => console.log("ОШИБКА: " + value));
modalToAuthorizationMethod.watch(() =>
  console.log("Модальное окно с содержимым метода авторизации."),
);
// => ОШИБКА: 500
// => Модальное окно с содержимым метода авторизации.

split(source, match)

Начиная с

Формула

split(source, match);

Аргументы

  1. source: Юнит, который будет запускать вычисления в split
  2. match (Объект): Схема кейсов, которая использует имена результирующих событий как ключи и функцию сопоставления*((value) => Boolean)*

Возвращает

(Объект) – Объект, имеющий ключи, определенные в аргументе match, плюс __(два подчеркивания) – который обозначает кейс по умолчанию (если ни одно из условий не выполнено).

Примеры

Базовый

import { createEvent, split } from "effector";

const message = createEvent();

const messageByAuthor = split(message, {
  bob: ({ user }) => user === "bob",
  alice: ({ user }) => user === "alice",
});
messageByAuthor.bob.watch(({ text }) => {
  console.log("[bob]: ", text);
});
messageByAuthor.alice.watch(({ text }) => {
  console.log("[alice]: ", text);
});

message({ user: "bob", text: "Привет" });
// => [bob]: Привет
message({ user: "alice", text: "Привет, bob" });
// => [alice]: Привет, bob

/* кейс по умолчанию, срабатывает, если ни одно из условий не выполнено */
const { __: guest } = messageByAuthor;
guest.watch(({ text }) => {
  console.log("[гость]: ", text);
});
message({ user: "незарегистрированный", text: "привет" });
// => [гость]: привет

Попробуйте

Обратите внимание

Только первое выполненное сопоставление вызовет результирующее событие

Другой пример

import { createEvent, split } from "effector";

const message = createEvent();

const { short, long, medium } = split(message, {
  short: (m) => m.length <= 5,
  medium: (m) => m.length > 5 && m.length <= 10,
  long: (m) => m.length > 10,
});

short.watch((m) => console.log(`короткое сообщение '${m}'`));
medium.watch((m) => console.log(`среднее сообщение '${m}'`));
long.watch((m) => console.log(`длинное сообщение '${m}'`));

message("Привет, Боб!");
// => длинное сообщение 'Привет, Боб!'

message("Привет!");
// => короткое сообщение 'Привет!'

Попробуйте

split({ source, clock?, match, cases })

Начиная с

Работает так же, как split с кейсами, однако вычисления в split будут запущены после срабатывания clock.

Формула

split({source, clock?, match, cases})

Аргументы

TBD

Примеры

import { createStore, createEvent, createEffect, split } from "effector";

const options = ["save", "delete", "forward"];
const $message = createStore({ id: 1, text: "Принесите мне чашку кофе, пожалуйста!" });
const $mode = createStore("");
const selectedMessageOption = createEvent();
const saveMessageFx = createEffect(() => "save");
const forwardMessageFx = createEffect(() => "forward");
const deleteMessageFx = createEffect(() => "delete");

$mode.on(selectedMessageOption, (mode, opt) => options.find((item) => item === opt) ?? mode);

split({
  source: $message,
  clock: selectedMessageOption,
  match: $mode,
  cases: {
    save: saveMessageFx,
    delete: deleteMessageFx,
    forward: forwardMessageFx,
  },
});

selectedMessageOption("delet"); // ничего не происходит
selectedMessageOption("delete");

Попробуйте

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

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

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

Соавторы