What does guard() do?
The guard() function is another key "building block" of Effector,
alongside sample() and forward().
In short:
guard()is a filter for reactive flows. It passes an event or effect further only if a condition (filter) is met.
1. What guard does
guard() takes a source and a condition (filter),
and sends data to the target only if the condition is true.
Metaphor:
"When data arrives, check it - and if everything is fine, pass it through."
2. The simplest example
import { createEvent, guard } from 'effector'
const numberEntered = createEvent<number>()
const evenNumberPassed = createEvent<number>()
guard({
source: numberEntered,
filter: (n) => n % 2 === 0,
target: evenNumberPassed,
})
evenNumberPassed.watch((n) => console.log('Even number:', n))
numberEntered(3) // does not pass
numberEntered(10) // Even number: 10Here guard "passes" data through only if the number is even.
3. Basic syntax
guard({
source, // data source (event, effect.doneData, store)
filter, // condition (a function or store<boolean>)
target, // where to send it if filter = true
})4. Example with a store filter
The filter can be not a function but a reactive store<boolean>:
import { createStore, createEvent } from 'effector'
const submitClicked = createEvent()
const $isValid = createStore(false)
const formSubmit = createEvent()
guard({
clock: submitClicked,
filter: $isValid,
target: formSubmit,
})Now formSubmit() will be called only if $isValid === true.
5. The difference between source and clock
guard has 2 modes of operation - just like sample:
| Parameter | What it does |
|---|---|
source | Where the data comes from |
clock | When the check happens |
For example:
guard({
source: $form,
clock: submitClicked,
filter: $isValid,
target: sendFormFx,
})That is:
"When
submitis clicked, take the data from$form, and if$isValidis true, send it tosendFormFx."
6. guard() and sample()
They are similar, but guard() is used when you just need to filter a flow,
not also transform the data.
| guard() | sample() | |
|---|---|---|
| Goal | Filter a flow | Sample data on an event |
Has fn (a transform)? | No | Yes |
| Main scenario | "Allow / forbid" | "Take and transform" |
| Often used for | Validation, access rights | Wiring logic |
7. A form validation example
const submitClicked = createEvent()
const $form = createStore({ email: 'a@b.com', password: '12345' })
const $isValid = createStore(true)
const sendFormFx = createEffect(async (form) => api.send(form))
guard({
source: $form,
clock: submitClicked,
filter: $isValid,
target: sendFormFx,
})Here:
- When "Submit" is clicked,
- Effector checks
$isValid, - If true -> it calls
sendFormFx($form).
8. An example filtering an async result
const fetchUserFx = createEffect(async (id: number) => {
const res = await fetch(`/api/users/${id}`)
return res.json()
})
const userLoaded = createEvent<any>()
guard({
source: fetchUserFx.doneData,
filter: (user) => user.isActive,
target: userLoaded,
})Only active users will be passed to userLoaded.
9. It can be combined with forward and sample
For example:
const logoutClicked = createEvent()
const $isAuth = createStore(true)
const clearSessionFx = createEffect(api.logout)
guard({
clock: logoutClicked,
filter: $isAuth,
target: clearSessionFx,
})Here guard checks the $isAuth state,
while with forward we would have to filter manually.
10. Visually (dataflow)
[source] → guard(filter = true) → [target]
[source] → guard(filter = false) (does not pass)Summary
guard()is a reactive filter in Effector that passes data through only if the condition is met.
It is especially useful for:
- validating data before requests (
filter: $isValid), - checking authorization,
- allowing actions depending on state,
- cleaning up an event flow.
A formula to remember it by
guard= "iffilter-> passsourcetotarget, otherwise - ignore".
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.