What is an "effect" in Effector?
In Effector, an effect is a reactive unit for handling asynchronous actions (requests, timers, API operations, etc.).
If an event is "something happened" and a store is "the current state",
then an effect is "something is running" (usually with a side effect).
1. What is an effect
An effect is a function, a wrapper around asynchronous logic, that automatically manages states:
pending,done,fail,finally.
Effector makes effects reactive: they can be triggered from events, update stores, trigger new events, and even call other effects.
2. Basic effect example
import { createEffect } from 'effector'
const fetchUserFx = createEffect(async (id: number) => {
const res = await fetch(`/api/users/${id}`)
if (!res.ok) throw new Error('Failed to load')
return res.json()
})
// Calling the effect
fetchUserFx(1)Here:
createEffect()creates a reactive effect.- Inside, there is a plain asynchronous function.
- Effector itself tracks when the effect:
- starts ->
pending = true, - finishes ->
done, - fails with an error ->
fail.
- starts ->
3. Automatic effect events
Each effect inside Effector creates 4 built-in events:
| Event | When it fires | Useful for |
|---|---|---|
.pending | while the effect is running | showing "Loading…" |
.done | when the effect finishes successfully | updating data |
.fail | when an error occurred | showing an error |
.finally | when the effect finished (either outcome) | clearing indicators, completion logic |
Example:
fetchUserFx.done.watch(({ params, result }) => {
console.log('Loaded the user', result)
})
fetchUserFx.fail.watch(({ error }) => {
console.error('Error:', error)
})4. Managing the effect's state
Each effect is not just a function, it's a reactive node.
It has a pending store that you can use in the UI:
import { useUnit } from 'effector-react'
function UserLoader() {
const [pending, loadUser] = useUnit([fetchUserFx.pending, fetchUserFx])
return (
<button onClick={() => loadUser(1)} disabled={pending}>
{pending ? 'Loading...' : 'Load user'}
</button>
)
}Effector synchronizes the pending value itself, with no manual setState.
5. How events and effects connect
Usually an effect is triggered through an event, not directly:
import { createEvent, sample } from 'effector'
const userRequested = createEvent<number>()
sample({
clock: userRequested,
target: fetchUserFx,
})Now userRequested(42) will trigger fetchUserFx(42).
6. Handling the result via a store
After the effect runs, data can be saved into a store:
import { createStore } from 'effector'
const $user = createStore(null)
.on(fetchUserFx.doneData, (_, user) => user)
.reset(fetchUserFx.fail)
$user.watch(console.log).doneData is a shortcut for effect.done.map(({ result }) => result).
7. The reactive chain "event → effect → store → UI"
[event: userRequested] → [effect: fetchUserFx] → [store: $user] → [UI]This is Effector's classic dataflow: the user triggers an event -> the effect performs the request -> the result reactively updates the store -> the UI updates automatically.
8. Difference from event and store
| event | effect | store | |
|---|---|---|---|
| Purpose | Report that something happened | Perform an async or side-effect operation | Store and update data |
| Returns a value | No | A promise | Data (via .getState()) |
| Can change state | Only through a link with a store | Only through .doneData/.failData | Yes |
| Reactivity | Yes | Yes | Yes |
9. Full scenario example
import { createEvent, createEffect, createStore, sample } from 'effector'
// 1. an event from the UI
const userRequested = createEvent<number>()
// 2. an asynchronous effect
const fetchUserFx = createEffect(async (id: number) => {
const res = await fetch(`/api/users/${id}`)
return res.json()
})
// 3. a store for the data
const $user = createStore(null).on(fetchUserFx.doneData, (_, user) => user)
// 4. link the event to the effect
sample({
clock: userRequested,
target: fetchUserFx,
})
// 5. listen to the result
$user.watch(console.log)
// call it
userRequested(10)Summary
An effect in Effector is a reactive asynchronous operation. It:
- performs side effects (requests, timers, API calls),
- manages loading and error state,
- links to other entities (events, stores),
- and integrates perfectly with the reactive data flow.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.