Effect

Effect is a container for async function.

It can be safely used in place of the original async function.

Arguments

  1. params (Params): parameters passed to effect

Returns

(Promise)

Example

import {createEffect, createStore} from 'effector'
const fetchUserFx = createEffect({
async handler({id}) {
const res = await fetch(`https://example.com/users/${id}`)
return res.json()
},
})
const users = createStore([]) // Default state
// add reducer for fetchUserFx.doneData event (triggered when handler resolved)
.on(fetchUserFx.doneData, (users, user) => [...users, user])
// subscribe to handler resolve
fetchUserFx.done.watch(({result, params}) => {
console.log(params) // => {id: 1}
console.log(result) // => resolved value
})
// subscribe to handler reject or throw error
fetchUserFx.fail.watch(({error, params}) => {
console.error(params) // => {id: 1}
console.error(error) // => rejected value
})
// you can replace function anytime
fetchUserFx.use(anotherHandler)
// call effect with your params
fetchUserFx({id: 1})
// handle promise
const data = await fetchUserFx({id: 2})

Try it

Effect Methods

use(handler)

Provides a function, which will be called when effect is triggered.

It will replace the previous function inside.

Note: You must provide a handler either through .use method or handler property in createEffect, otherwise the error "no handler used in %effect name%" will appear in the console

See also: Testing api calls with effects and stores

Arguments

  1. handler (Function): Function, that receives the first argument passed to an effect call.

Returns

(Effect): The same effect

Example

const fetchUserReposFx = createEffect()
fetchUserReposFx.use(async params => {
console.log('fetchUserReposFx called with', params)
const url = `https://api.github.com/users/${params.name}/repos`
const req = await fetch(url)
return req.json()
})
fetchUserReposFx({name: 'zerobias'})
// => fetchUserRepos called with {name: 'zerobias'}

Try it


watch(watcher)

Subscribe to effect calls.

Formulae

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

Arguments

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

Returns

Subscription: Unsubscribe function.

Example

import {createEffect} from 'effector'
const effectFx = createEffect({
handler: value => value,
})
const unsubscribe = effectFx.watch(payload => {
console.log('called with', payload)
unsubscribe()
})
effectFx(10) // => called with 10
effectFx(20) // nothing, cause watcher unsubscribed

Try it


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 event = effect.prepend(fn)
  • When event is triggered
  • Call fn with payload from event
  • Call effect with result of fn()

Arguments

  1. fn (Function): A function that receives payload, should be pure.

Returns

Event: New event.


use.getCurrent()

Returns current handler of effect. Useful for testing.

Returns

(Function): Current handler, defined by handler property or via use call.

Example

const handlerA = () => 'A'
const handlerB = () => 'B'
const fx = createEffect({handler: handlerA})
console.log(fx.use.getCurrent() === handlerA)
// => true
fx.use(handlerB)
console.log(fx.use.getCurrent() === handlerB)
// => true

Try it


Effect Properties

doneData

Event, which is triggered with result of the effect execution:

Event triggered when handler is resolved.

Example

import {createEffect} from 'effector'
const effectFx = createEffect({
handler: value => Promise.resolve(value + 1),
})
effectFx.doneData.watch(result => {
console.log('Done with result', result)
})
effectFx(2) // => Done with result 3

Try it

failData

Event, which is triggered with error thrown by the effect:

Event triggered when handler is rejected or throws error.

Example

import {createEffect} from 'effector'
const effectFx = createEffect()
effectFx.use(value => Promise.reject(value - 1))
effectFx.failData.watch(error => {
console.log('Fail with error', error)
})
effectFx(2) // => Fail with error 1

Try it

done

Event, which is triggered when handler is resolved.

Properties

Event triggered with object of params and result:

  1. params (Params): An argument passed to the effect call
  2. result (Done): A result of the resolved handler

Example

import {createEffect} from 'effector'
const effectFx = createEffect({
handler: value => Promise.resolve(value + 1),
})
effectFx.done.watch(({params, result}) => {
console.log('Done with params', params, 'and result', result)
})
effectFx(2) // => Done with params 2 and result 3

Try it

fail

Event, which is triggered when handler is rejected or throws error.

Properties

Event triggered with object of params and error:

  1. params (Params): An argument passed to effect call
  2. error (Fail): An error catched from the handler

Example

import {createEffect} from 'effector'
const effectFx = createEffect()
effectFx.use(value => Promise.reject(value - 1))
effectFx.fail.watch(({params, error}) => {
console.log('Fail with params', params, 'and error', error)
})
effectFx(2) // => Fail with params 2 and error 1

Try it

finally

Event, which is triggered when handler is resolved, rejected or throws error.

Properties

Event, which is triggered with object of status, params and error or result:

  1. status (string): A status of effect (done or fail)
  2. params (Params): An argument passed to effect call
  3. error (Fail): An error catched from the handler
  4. result (Done): A result of the resolved handler

Example

import {createEffect} from 'effector'
const fetchApiFx = createEffect({
handler: ms => new Promise(resolve => setTimeout(resolve, ms, `${ms} ms`)),
})
fetchApiFx.finally.watch(console.log)
fetchApiFx(100)
// if resolved
// => {status: 'done', result: '100 ms', params: 100}
// if rejected
// => {status: 'fail', error: Error, params: 100}

Try it

pending

Store will update when done or fail are triggered. Store contains true value until the effect is resolved or rejected.

Example

import React from 'react'
import {createEffect} from 'effector'
import {useStore} from 'effector-react'
const fetchApiFx = createEffect({
handler: ms => new Promise(resolve => setTimeout(resolve, ms)),
})
fetchApiFx.pending.watch(console.log)
const Loading = () => {
const loading = useStore(fetchApiFx.pending)
return <div>{loading ? 'Loading...' : 'Load complete'}</div>
}
ReactDOM.render(<Loading />, document.getElementById('root'))
fetchApiFx(3000)

Try it

It's a shorthand for common use case

import {createEffect, createStore} from 'effector'
const fetchApiFx = createEffect()
//now you can use fetchApiFx.pending instead
const isLoading = createStore(false)
.on(fetchApiFx, () => true)
.on(fetchApiFx.done, () => false)
.on(fetchApiFx.fail, () => false)

inFlight

Store which show how many effect calls aren't settled yet. Useful for rate limiting.

Example

import {createEffect} from 'effector'
const fx = createEffect({
handler: () => new Promise(rs => setTimeout(rs, 500)),
})
fx.inFlight.watch(amount => {
console.log('in-flight requests:', amount)
})
// => 0
const req1 = fx()
// => 1
const req2 = fx()
// => 2
await Promise.all([req1, req2])
// => 1
// => 0

Try it