Effect
Effect is a container for async function.
It can be safely used in place of the original async function.
Arguments
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 resolvefetchUserFx.done.watch(({result, params}) => { console.log(params) // => {id: 1} console.log(result) // => resolved value})
// subscribe to handler reject or throw errorfetchUserFx.fail.watch(({error, params}) => { console.error(params) // => {id: 1} console.error(error) // => rejected value})
// you can replace function anytimefetchUserFx.use(anotherHandler)
// call effect with your paramsfetchUserFx({id: 1})
// handle promiseconst data = await fetchUserFx({id: 2})
Effect Methods
use(handler)
Provides a function, which will be called when an effect is triggered.
It will replace the previous function inside (if any).
Arguments
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'}
watch(watcher)
Subscribe to effect calls.
Arguments
watcher
(Watcher): A function that receivespayload
.
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 10effectFx(20) // nothing, cause watcher unsubscribed
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.
Arguments
fn
(Function): A function that receivespayload
, 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
Effect Properties
doneData
Event triggered when handler is resolved.
Arguments
Event triggered with result of effect execution:
result
(Done): A result of the resolved handler
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
failData
Event triggered when handler is rejected or throws error.
Arguments
Event triggered with error thrown by effect:
error
(Fail): An error thrown by handler
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
done
Event triggered when handler is resolved.
Arguments
Event triggered with object of params
and result
:
params
(Params): An argument passed to the effect callresult
(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
fail
Event triggered when handler is rejected or throws error.
Arguments
Event triggered with object of params
and error
:
params
(Params): An argument passed to effect callerror
(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
finally
Event triggered when handler is resolved, rejected or throws error.
Arguments
Event triggered with object of status
, params
and error
or result
:
status
(string): A status of effect (done
orfail
)params
(Params): An argument passed to effect callerror
(Fail): An error catched from the handlerresult
(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}
pending
Store will update when done
or fail
are triggered.
Store contains a 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)
It's a shorthand for common use case
import {createEffect, createStore} from 'effector'
const fetchApiFx = createEffect()
//now you can use fetchApiFx.pending insteadconst 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