Що робить merge()?
Що таке merge
merge()об'єднує декілька подій (або потоків) в одну. Воно створює нову подію, яка спрацьовує щоразу, коли спрацьовує будь-яка з вихідних подій.
Метафора:
"У мене є декілька джерел подій, але я хочу реагувати на них як на одне".
Простий приклад
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
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 тощо):
const loadUserFx = createEffect(...)
const loadPostsFx = createEffect(...)
const dataLoaded = merge([loadUserFx.doneData, loadPostsFx.doneData])
dataLoaded.watch(() => console.log('Щось завантажилося'))Зручно, коли потрібно реагувати "на все, що завершилося".
5. Частий патерн: об'єднати різні події одного типу
Наприклад, якщо у тебе декілька дій, які повинні вести до одного результату:
const clickedBuy = createEvent()
const clickedAddToCart = createEvent()
const clickedFavorite = createEvent()
const productInteracted = merge([clickedBuy, clickedAddToCart, clickedFavorite])
productInteracted.watch(() => console.log('Користувач взаємодіяв з товаром'))Тепер неважливо, яка саме дія, логіка буде запускатися однаково.
6. Комбінування merge з іншими операторами
merge() часто використовується як перший крок перед guard() або sample():
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. Візуально
[eventA] ─┐
├──> [merge] → [target]
[eventB] ─┘Щоразу, коли спрацьовує eventA або eventB, нова об'єднана подія теж спрацьовує.
9. Приклад із реального застосунку
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 акуратно виводить типи:
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().
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.