Event

Event is an intention to change state. Let's imagine life situation, you come to a shop and on etiquette you should say "hello" - intention, then you say "hello" - event.

Event calls always returns its payload:

import {createEvent} from 'effector'
const event = createEvent()
console.log(event(1))
// => 1
console.log(event())
// => undefined

Try it

Event Methods

watch(watcher)

It is a function which allows you to follow the event or to create side-effects.

Formulae

const unwatch = event.watch(fn)
  • Call fn on each event trigger, pass payload of event as argument to fn
  • When unwatch is called, stop calling fn on each event trigger

Arguments

  1. watcher (Watcher): A function that receives payload.

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

Try it


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 from first to fn
  • Trigger second with the result of the fn() call as payload

Arguments

  1. fn (Function): A function that receives payload, 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() method
const 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

Try it


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 the concrete size of the sneakers model, besides you want to receive a notification if there will have and don't receive others. Therefore filtering is needed for that. Event filtering works the same. If the filter returns true, the event will be called.

Formulae

const second = first.filter({fn})
  • When first is triggered, pass payload from first to fn
  • If fn() returns true, second will be triggered with payload from first

Arguments

  1. fn (Function): A function that receives payload, 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 triggered
numbers({x: -10}) // store won't triggered
numbers({x: 10}) // store will triggered

Try it


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 you come to the product shop and you have let's say a task: you should buy 10 apples, but only red otherwise nothing. Let's consider by steps:

  1. Take one apple;
  2. Have a look red(put in a pack) or no(take another).

And you repeat this till no complete a task. Now think about it in Effector context and we consider the positive case:

  1. Take an apple - event;
  2. Have a look red or no - filter;
  3. You keep it - map;
  4. Put in pack - event.
  5. 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, call fn with payload from first
    • If fn() returned undefined do not trigger second
    • If fn() returned some data, trigger second with data from fn()

Arguments

  1. fn (Function): A function that receives payload, 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'))

Try it


prepend(fn)

Creates an event, upon trigger it does send transformed data into source event. Works kind of like reverse .map. In the 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 from second
  • Trigger first with result of fn()

Arguments

  1. fn (Function): A function that receives payload, 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 element
const input = document.createElement('input')
input.onchange = inputChanged
document.body.appendChild(input)
// input something in input, and press Enter
// => Current name is: something

Try it