What does split() do?
What split is
split()is an operator that splits a single stream (event/effect) into several branches based on a condition (match) or a feature (cases).
In simpler terms:
"When an event arrives, send it to the right category based on its content."
1. A simple example
import { createEvent, split } from 'effector'
const userAction = createEvent<'login' | 'logout' | 'signup'>()
const { login, logout, signup } = split({
source: userAction,
match: {
login: (type) => type === 'login',
logout: (type) => type === 'logout',
signup: (type) => type === 'signup',
},
})
login.watch(() => console.log('Logged in'))
logout.watch(() => console.log('Logged out'))
signup.watch(() => console.log('Signed up'))
userAction('signup') // → "Signed up"
userAction('logout') // → "Logged out"Here split() takes one event (userAction)
and creates three new events (login, logout, signup),
each of which fires only when its own condition matches.
2. Syntax
split({
source, // event or effect.doneData
match, // an object of filter functions
cases?, // an object of ready-made events to assign to
})3. Example with a data object
const formSubmitted = createEvent<{ type: 'login' | 'signup'; data: any }>()
const { login, signup } = split({
source: formSubmitted,
match: {
login: ({ type }) => type === 'login',
signup: ({ type }) => type === 'signup',
},
})
login.watch(({ data }) => console.log('Logging in:', data))
signup.watch(({ data }) => console.log('Signing up:', data))
formSubmitted({ type: 'signup', data: { name: 'Alex' } })
// → "Signing up: { name: 'Alex' }"split simply "routes" the incoming payload to the right event based on the condition.
4. Example with an effect
split works great with effects, especially with .done, .fail, and .finally:
import { createEffect } from 'effector'
const fetchUserFx = createEffect(async (id: number) => {
const res = await fetch(`/api/users/${id}`)
if (!res.ok) throw new Error('Not found')
return res.json()
})
const { success, failure } = split({
source: fetchUserFx.finally,
match: {
success: ({ status }) => status === 'done',
failure: ({ status }) => status === 'fail',
},
})
success.watch(({ result }) => console.log('User:', result))
failure.watch(({ error }) => console.error('Error:', error))This is a very common pattern: splitting an effect's successful and unsuccessful outcome without manual checks.
5. Using it with pre-created events (cases)
If events are already declared, you can simply "route" the streams:
const loginEvent = createEvent()
const signupEvent = createEvent()
split({
source: userAction,
match: {
login: (t) => t === 'login',
signup: (t) => t === 'signup',
},
cases: {
login: loginEvent,
signup: signupEvent,
},
})Now userAction('login') will call loginEvent().
6. What split does under the hood
split() is like several guard() calls in a row,
but with a convenient declarative syntax and automatic event generation.
Equivalent to this:
const login = guard({ source: userAction, filter: (t) => t === 'login' })
const logout = guard({ source: userAction, filter: (t) => t === 'logout' })But split() does all of it for you in one call.
7. You can add a "default" route
If no condition matches, __ (underscore) fires:
const action = createEvent<string>()
const { ok, fail, __: unknown } = split({
source: action,
match: {
ok: (v) => v === 'ok',
fail: (v) => v === 'fail',
},
})
unknown.watch(() => console.warn('Unknown action'))
action('cancel') // → "Unknown action"8. Typing split in TypeScript
Effector smartly infers types for all branches:
const action = createEvent<'a' | 'b' | 'c'>()
const { a, b, c } = split({
source: action,
match: {
a: (x): x is 'a' => x === 'a',
b: (x): x is 'b' => x === 'b',
c: (x): x is 'c',
},
})Now a, b, c have strictly typed payloads -
TypeScript knows that a can only be 'a'.
9. Visually
[source event]
│
┌───────────┼────────────┐
▼ ▼ ▼
[caseA] [caseB] [caseC]Each condition creates its own "stream branch".
10. Practical scenarios
| Scenario | What split does |
|---|---|
| Handling different action types | Splits "login", "signup", "logout" |
| Splitting an effect's outcomes | success / failure |
| Filtering by data status | active / archived / deleted |
| Branching business logic | depending on the type of user |
Summary
split()is a reactive "switch-case" in Effector. It:
- takes one stream (
source),- checks every
match,- creates (or routes into) new events,
- sends the payload to the right branch.
Formula to remember
split({ source, match: { A, B, C } })⇒ createsA(),B(),C()⇒ calls the matching one when its condition is met.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.