Skip to main content

Що робить merge()?

Що таке merge

merge() об'єднує декілька подій (або потоків) в одну. Воно створює нову подію, яка спрацьовує щоразу, коли спрацьовує будь-яка з вихідних подій.

Метафора:

"У мене є декілька джерел подій, але я хочу реагувати на них як на одне".


Простий приклад

javascript
import { createEvent, merge } from 'effector' const loginClicked = createEvent() const registerClicked = createEvent() const authStarted = merge([loginClicked, registerClicked]) authStarted.watch(() => console.log('Починаємо авторизацію')) loginClicked() // -> "Починаємо авторизацію" registerClicked() // -> "Починаємо авторизацію"

Тобто authStarted буде викликатися при будь-якій з цих подій.


2. Що повертає merge

merge() повертає нову подію, у яку "вплавлені" всі події з масиву.

Тип нової події = об'єднання (union) payload'ів вихідних подій.


3. Приклад з payload

javascript
const emailLogin = createEvent<{ email: string }>() const phoneLogin = createEvent<{ phone: string }>() const login = merge([emailLogin, phoneLogin]) login.watch((data) => console.log('Логін:', data)) emailLogin({ email: 'a@b.com' }) // -> { email: 'a@b.com' } phoneLogin({ phone: '+123456' }) // -> { phone: '+123456' }

Effector не втрачає дані - він просто об'єднує потоки. Payload зберігається від кожного джерела.


4. Можна об'єднувати й ефекти

merge() працює і з ефектами (через .doneData, .fail, .finally тощо):

javascript
const loadUserFx = createEffect(...) const loadPostsFx = createEffect(...) const dataLoaded = merge([loadUserFx.doneData, loadPostsFx.doneData]) dataLoaded.watch(() => console.log('Щось завантажилося'))

Зручно, коли потрібно реагувати "на все, що завершилося".


5. Частий патерн: об'єднати різні події одного типу

Наприклад, якщо у тебе декілька дій, які повинні вести до одного результату:

javascript
const clickedBuy = createEvent() const clickedAddToCart = createEvent() const clickedFavorite = createEvent() const productInteracted = merge([clickedBuy, clickedAddToCart, clickedFavorite]) productInteracted.watch(() => console.log('Користувач взаємодіяв з товаром'))

Тепер неважливо, яка саме дія, логіка буде запускатися однаково.


6. Комбінування merge з іншими операторами

merge() часто використовується як перший крок перед guard() або sample():

javascript
const loginClicked = createEvent() const registerClicked = createEvent() const authClicked = merge([loginClicked, registerClicked]) guard({ source: authClicked, filter: $isAuthEnabled, target: startAuthFx, })

Так ти об'єднуєш усі можливі способи запуску одного потоку логіки.


7. Поведінка

  • merge() не змінює payload;
  • не дублює події - просто об'єднує їх;
  • можна передати масив будь-якої довжини;
  • працює з будь-яким типом event/effect.doneData;
  • результат - нова подія, на яку можна підписуватися або направляти далі (forward, sample, guard тощо).

8. Візуально

javascript
[eventA] ─┐ ├──> [merge][target] [eventB] ─┘

Щоразу, коли спрацьовує eventA або eventB, нова об'єднана подія теж спрацьовує.


9. Приклад із реального застосунку

javascript
const openedFromMenu = createEvent() const openedFromSearch = createEvent() const openedFromLink = createEvent() const pageOpened = merge([openedFromMenu, openedFromSearch, openedFromLink]) pageOpened.watch(() => console.log('Сторінка відкрита'))

Тепер можна зручно логувати одну подію pageOpened, замість трьох окремих watch.


10. Типізація merge у TypeScript

Effector акуратно виводить типи:

javascript
const e1 = createEvent<number>() const e2 = createEvent<string>() const merged = merge([e1, e2]) // тип merged: Event<number | string>

Тобто payload об'єднується в union. TypeScript коректно знає, що merged може передавати або число, або рядок.


Підсумок

merge() об'єднує декілька подій (або ефектів) в одну. Воно створює нову подію, яка спрацьовує при будь-якій з вихідних, передаючи їх payload "як є".


Формула для запам'ятовування

merge([A, B, C]) -> D, де D() викликається при кожному A(), B(), C().

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.