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
const fetchUser = createEffect({
handler: ({id}) => {
return fetch(`https://example.com/users/${id}`).then(res => res.json())
},
})
const users = createStore([]) // Default state
// add reducer for fetchUser.done event (triggered when handler resolved)
.on(fetchUser.done, (users, {result: user}) => [...users, user])
// subscribe to handler resolve
fetchUser.done.watch(({result, params}) => {
console.log(params) // => {id: 1}
console.log(result) // => resolved value
})
// subscribe to handler reject or throw error
fetchUser.fail.watch(({error, params}) => {
console.error(params) // => {id: 1}
console.error(error) // => rejected value
})
// you can replace function anytime
fetchUser.use(anotherHandler)
// call effect with your params
fetchUser({id: 1})
// handle promise
const data = await fetchUser({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
): A container for async function.
Example
const fetchUserRepos = createEffect()
fetchUserRepos.use(async params => {
console.log('fetchUserRepos called with', params)
const url = `https://api.github.com/users/${params.name}/repos`
const req = await fetch(url)
return req.json()
})
fetchUserRepos({name: 'zerobias'}) // => fetchUserRepos called with {name: 'zerobias'}
watch(watcher)
Subscribe to effect calls.
Arguments
watcher
(Function): A function that receivespayload
.
Returns
(Subscription
): A function that unsubscribes the watcher.
Example
const effect = createEffect({
handler: value => value,
})
const unsubscribe = effect.watch(payload => {
console.log('called with', payload)
unsubscribe()
})
effect(10) // => called with 10
effect(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
): An intention to change state.
Effect Properties
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
const effect = createEffect({
handler: value => Promise.resolve(value + 1),
})
effect.done.watch(({params, result}) => {
console.log('Done with params', params, 'and result', result)
})
effect(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
const effect = createEffect()
effect.use(value => Promise.reject(value - 1))
effect.fail.watch(({params, error}) => {
console.log('Fail with params', params, 'and error', error)
})
effect(2) // => Fail with params 2 and error 1
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 {createComponent} from 'effector-react'
const fetchApi = createEffect({
handler: ms => new Promise(resolve => setTimeout(resolve, ms)),
})
fetchApi.pending.watch(console.log)
const Loading = createComponent(
fetchApi.pending,
(props, pending) => pending && <div>Loading...</div>,
)
fetchApi(5000)
ReactDOM.render(<Loading />, document.getElementById('root'))
It's a shorthand for common use case
import {createEffect, createStore} from 'effector'
const fetchApi = createEffect()
//now you can use fetchApi.pending instead
const isLoading = createStore(false)
.on(fetchApi, () => true)
.on(fetchApi.done, () => false)
.on(fetchApi.fail, () => false)
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 fetchApi = createEffect({
handler: ms => new Promise(resolve => setTimeout(resolve, ms, `${ms} ms`)),
})
fetchApi.finally.watch(console.log)
fetchApi(100)
// if resolved
// => {status: 'done', result: '100 ms', params: 100}
// if rejected
// => {status: 'fail', error: Error, params: 100}