split
since
effector 20.0.0
Pattern matching method, splits trigger unit (event, effect or store) into several events, which fires when trigger matches its matching function
split({source, match, cases})
Arguments
source
(Event | Effect | Store): Event, Effect or Store unit-trigger.match
(Object): 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 correspondingcases[fieldName]
(if there is one), if none of the functions returns true, then the data will be sent tocases.__
(if there is one)cases
(Object): An object with units (Event, Effect or Store) to which data will be passed fromsource
if the corresponding matching function returns true
Returns
void
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
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']
Split object form
since
effector 21.0.0
split(source, cases)
Arguments
source
(Event | Effect | Store): Event, Effect or Store unit-trigger.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 cases
argument, plus __
(two underscores) - which stands for default
(no matches met) case.
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
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!'