split

Choose one of cases by matching functions. It "splits" source unit into several events, which fires when payload matches their matching function. Works like pattern matching for payload values

split with cases

split({source, match, cases})

Arguments

  • source: Unit which will trigger computation in split
  • match: Object with the functions-matches to which the data sent to the source will be sequentially matched. If one of the functions returns true, then the data will be sent to the corresponding cases[fieldName] (if there is one), if none of the functions returns true, then the data will be sent to cases.__ (if there is one)
  • cases: Object with units to which data will be passed from source if the corresponding matching function returns true

Returns

void
since

effector 21.0.0

Example 1

import {split, createEffect, createEvent} from 'effector'
const messageReceived = createEvent()
const showTextPopup = createEvent()
const playAudio = createEvent()
const reportUnknownMessageType = createEffect(({type}) => {
console.log('unknown message:', type)
})
split({
source: messageReceived,
match: {
text: msg => msg.type === 'text',
audio: msg => msg.type === 'audio',
},
cases: {
text: showTextPopup,
audio: playAudio,
__: reportUnknownMessageType,
},
})
showTextPopup.watch(({value}) => {
console.log('new message:', value)
})
messageReceived({
type: 'text',
value: 'Hello',
})
// => new message: Hello
messageReceived({
type: 'image',
imageUrl: '...',
})
// => unknown message: image

Try it

Example 2

You can match directly to store api as well:

import {split, createStore, createEvent, createApi} from 'effector'
const textContent = createStore([])
const messageReceived = createEvent()
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, `audio ${duration} ms`],
__: list => [...list, 'unknown message'],
}),
})
textContent.watch(messages => {
console.log(messages)
})
messageReceived({
type: 'text',
value: 'Hello',
})
// => ['Hello']
messageReceived({
type: 'image',
imageUrl: '...',
})
// => ['Hello', 'unknown message']
messageReceived({
type: 'audio',
duration: 500,
})
// => ['Hello', 'unknown message', 'audio 500 ms']

Try it

split without explicit cases

split(source, match)

Arguments

  1. source: Unit which will trigger computation in split
  2. match (Object): Schema of cases, which uses names of resulting events as keys, and matching function((value) => Boolean)

Returns

(Object) - Object, having keys, defined in match argument, plus __(two underscores) - which stands for default (no matches met) case.

since

effector 20.0.0

Example 1

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: 'Hello'})
// => [bob]: Hello
message({user: 'alice', text: 'Hi bob'})
// => [alice]: Hi bob
/* default case, triggered if no one condition met */
const {__: guest} = messageByAuthor
guest.watch(({text}) => {
console.log('[guest]: ', text)
})
message({user: 'unregistered', text: 'hi'})
// => [guest]: hi

Try it

note

Only the first met match will trigger resulting event

Example 2

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(`short message '${m}'`))
medium.watch(m => console.log(`medium message '${m}'`))
long.watch(m => console.log(`long message '${m}'`))
message('Hello, Bob!')
// => long message 'Hello, Bob!'
message('Hi!')
// => short message 'Hi!'

Try it

Last updated on