What does sample() do in Effector?
1. What sample is
sample() is a mechanism for reactively binding data between a source (
source) and a "trigger" (clock). When an event (clock) happens, sample "takes" the current value (source) and passes it further, totargetorfn.
In other words, sample = "When this happens, take that and do such-and-such".
2. Basic example
import { createEvent, createStore, sample } from 'effector'
const nameChanged = createEvent<string>()
const submitClicked = createEvent()
const $name = createStore('')
$name.on(nameChanged, (_, value) => value)
sample({
source: $name,
clock: submitClicked,
fn: (name) => `Submitting the form with name: ${name}`,
target: console.log,
})
nameChanged('Alex')
submitClicked()
// => "Submitting the form with name: Alex"Explanation:
- clock (trigger) = submitClicked
- source (data) = $name
- when submitClicked is clicked, the current $name is taken
- fn() creates the result, which goes to target
3. Mnemonic:
sample = "clock happened -> take a snapshot from source"
4. Parameters of sample
sample({
source, // where we get data from
clock, // when we do this
fn, // how we transform it
filter, // (optional) when it's allowed to pass through
target, // where the result goes (event, effect, store)
})Example with filter:
sample({
source: $form,
clock: submitClicked,
filter: $formValid,
target: sendFormFx,
})We'll submit the form (sendFormFx) only if $formValid === true.
5. Example of linking multiple sources
source can be not just a single store, but an object of several stores:
sample({
source: { name: $name, email: $email },
clock: submitClicked,
fn: ({ name, email }) => ({ name, email }),
target: sendFormFx,
})Now sample will grab the values of both stores at once, at the moment of the click.
6. Visually (data flow)
[source] ---\
> sample() ---> [target]
[clock] ----/- source -> where we get the data from
- clock -> what triggers "taking the sample"
- target -> where the result goes
7. Why sample is better than .watch() or .on()
| .watch() | .on() | sample() | |
|---|---|---|---|
| Reacts to a change? | Always | Always | Only on clock |
| Controls the moment in time | No | No | Yes |
| Allows filtering and linking | No | No | Yes |
| Used for reactive flows | Partially | No | The main tool |
Example:
sample({
source: $user,
clock: logoutClicked,
fn: () => null,
target: $user,
})Clicking logout resets $user. .on() wouldn't work here, because this isn't just a store change, it's an action tied to an event.
8. A real example from an application
const loginClicked = createEvent()
const $credentials = createStore({ email: '', password: '' })
const loginFx = createEffect(async (creds) => api.login(creds))
sample({
clock: loginClicked,
source: $credentials,
filter: $isFormValid,
target: loginFx,
})Now everything is reactive:
- on clicking "Login"
- if the form is valid
- we send $credentials to loginFx.
No extra useEffect, if, setState: pure reactive logic.
9. Combining sample
You can call sample() in a chain to build dependency graphs:
const submitClicked = createEvent()
const $data = createStore({ name: 'Alex' })
const saveFx = createEffect(api.saveUser)
const saved = sample({ clock: submitClicked, source: $data, target: saveFx })
sample({
clock: saveFx.doneData,
fn: () => 'Saved successfully!',
target: console.log,
})10. A common pattern: sample instead of "if/await/useEffect"
Effector's philosophy:
"No if (formValid) sendForm() at all: everything is described reactively through sample and filter".
This lets you write clean, deterministic business logic, where the order of actions is always predictable.
SUMMARY
sample() is Effector's foundation for reactive bindings: when one event (clock) happens, the library takes the current data from source, optionally filters/transforms it, and sends the result to target.
Formula to remember:
clock happens -> "sample" source -> fn() -> target.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.