Event
Event is an intention to change the state. Let's imagine life situation, you enter a shop and, according to etiquette, you have to say "hello" - intention, then you say "hello" - event.
Event calls always return its payload:
import {createEvent} from 'effector'
const event = createEvent()
console.log(event(1))// => 1console.log(event())// => undefined
Event Methods
watch(watcher)
It is a function which allows you to watch the event or to create side-effects.
Formulae
const unwatch = event.watch(fn)
- Call
fn
on eachevent
trigger, pass payload ofevent
as argument tofn
- When
unwatch
is called, stop callingfn
on eachevent
trigger
Arguments
watcher
(Watcher): A function that receivespayload
.
Returns
Subscription: Unsubscribe function.
Example
import {createEvent} from 'effector'
const sayHi = createEvent()const unwatch = sayHi.watch(name => console.log(`${name}, hi there!`))
sayHi('Peter') // => Peter, hi there!unwatch()
sayHi('Drew') // => nothing happened
map(fn)
Creates a new event, which will be called after the original event is called, applying the result of a fn
as a payload. It is special function which allows you to decompose dataflow, extract or transform data.
Formulae
const second = first.map(fn)
- When
first
is triggered, pass payload fromfirst
tofn
- Trigger
second
with the result of thefn()
call as payload
Arguments
fn
(Function): A function that receivespayload
, should be pure.
Returns
Event: New event.
Example
import {createEvent} from 'effector'
const userUpdated = createEvent()const userNameUpdated = userUpdated.map(({name}) => name) // you may decompose dataflow with .map() methodconst userRoleUpdated = userUpdated.map(({role}) => role.toUpperCase()) // either way you can transform data
userNameUpdated.watch(name => console.log(`User's name is [${name}] now`))userRoleUpdated.watch(role => console.log(`User's role is [${role}] now`))
userUpdated({name: 'john', role: 'admin'})// => User's name is [john] now// => User's role is [ADMIN] now
filter({fn})
Creates a new event, which will be called after the original event is called if fn
returns true
.
Let's assume a standard situation when you want to buy sneakers in the shop, but there is no size. You subscribe to a particular size of the sneakers model, and in addition, you want to receive a notification if they have it, and ignore any other notification. Therefore filtering can be helpful for that. Event filtering works in the same way. If filter returns true
, the event will be called.
Formulae
const second = first.filter({fn})
- When
first
is triggered, pass payload fromfirst
tofn
- If
fn()
returnstrue
,second
will be triggered with payload fromfirst
Arguments
fn
(Function): A function that receivespayload
, should be pure.
Returns
Event: New event.
Example
import {createEvent, createStore} from 'effector'
const numbers = createEvent('event with {x: number}')
const positiveNumbers = numbers.filter({ fn: ({x}) => x > 0,})
const lastPositive = createStore(0).on(positiveNumbers, (n, {x}) => x)
numbers({x: 0}) // store won't triggerednumbers({x: -10}) // store won't triggerednumbers({x: 10}) // store will triggered
filterMap(fn)
Creates a new event, which will be called after the original event is called if fn
returns a value other than undefined.
Imagine a situation, you come up to a grocery store and you have let's say a task: you need to buy 10 apples, but only those that are red, otherwise nothing.
Let's consider by steps:
- Take one apple;
- Have a look, is it red(put in a pack) or not(take another).
And you repeat this until you complete the task. Now think about it in the Effector terms and we consider the positive case:
- Take an apple - event;
- Have a look, red or no - filter;
- You keep it - map;
- Put in pack - event.
- Pack - store
You may see that we united filter()
and map()
methods, the reason for creating was an impossibility to event filtering.
Formulae
const second = first.filterMap(fn)
- When
first
is triggered, callfn
with payload fromfirst
- If
fn()
returnedundefined
do not triggersecond
- If
fn()
returned some data, triggersecond
with data fromfn()
- If
Arguments
fn
(Function): A function that receivespayload
, should be pure.
Returns
Event: New event.
Example
import React from 'react'import ReactDOM from 'react-dom'import {createEvent, createStore} from 'effector'
const openModal = createEvent('open that modal')const closeModal = createEvent('close that modal')
const openModalUnboxed = openModal.filterMap(ref => { if (ref.current) return ref.current})
openModalUnboxed.watch(modal => modal.showModal())
closeModal .filter({ fn: ref => { if (ref.current) return ref.current }, }) .watch(modal => modal.close())
const modalRef = React.createRef()
const App = () => ( <> <dialog ref={modalRef}> <form method="dialog"> <fieldset> <legend>Modal</legend> Tap to close <button type="submit" onSubmit={() => closeModal(modalRef)}> ❌ </button> </fieldset> </form> </dialog>
<button onClick={() => openModal(modalRef)}>Open modal</button> </>)
ReactDOM.render(<App />, document.getElementById('root'))
prepend(fn)
Creates an event, upon trigger it sends transformed data into the source event. Works kind of like reverse .map
. In case of .prepend
data transforms before the original event occurs and in the case of .map
, data transforms after original event occurred.
Formulae
const second = first.prepend(fn)
- When
second
event is triggered - Call
fn
with payload fromsecond
- Trigger
first
with result offn()
Arguments
fn
(Function): A function that receivespayload
, should be pure.
Returns
Event: New event.
Example
import {createEvent} from 'effector'
const nameChanged = createEvent()nameChanged.watch(name => console.log(`Current name is: ${name}`))
const inputChanged = nameChanged.prepend(e => e.target.value) // event, which will be bound to DOM elementconst input = document.createElement('input')input.onchange = inputChanged
document.body.appendChild(input)// input something in input, and press Enter// => Current name is: something