guard

Method for conditional event routing. It provides a way to control one dataflow with the help of another: when the condition and the data are in different places, we can use guard with stores as filters to trigger events when condition state is true, thereby modulate signals without mixing them.

Formulae

guard({ source, filter, target? }): target

When source is triggered, check filter for thruthy and call target with data from source if true.

  • If target is not passed, create Event with type of source and return it from guard()
  • If filter is Store, check it value for thruthy
  • If filter is Function, call it with data from source and check result for thruthy

guard({source, filter, target?})

Arguments

  1. params (Object): Configuration object

Returns

Event, which fires upon clock trigger

Example

import { createStore, createEffect, createEvent, guard, sample } from 'effector'
const clickRequest = createEvent()
const fetchRequest = createEffect({
handler: (n) => new Promise((rs) => setTimeout(rs, 2500, n)),
})
const clicks = createStore(0).on(clickRequest, (x) => x + 1)
const requests = createStore(0).on(fetchRequest, (x) => x + 1)
const isIdle = fetchRequest.pending.map((pending) => !pending)
/*
on clickRequest, take current clicks value,
and call fetchRequest with it
if isIdle value is true
*/
guard({
source: sample(clicks, clickRequest),
filter: isIdle,
target: fetchRequest,
})

See ui visualization

Also, guard accepts a common function predicate as filter, to drop events before forwarding them to target

Example 2

import { createEffect, createEvent, guard } from 'effector'
const searchUser = createEffect()
const submitForm = createEvent()
guard({
source: submitForm,
filter: (user) => user.length > 0,
target: searchUser,
})
submitForm('') // nothing happens
submitForm('alice') // ~> searchUser('alice')

Try it

guard(source, {filter: booleanStore})

Arguments

  1. source (Store/Event/Effect): Source unit. Will trigger given guard on updates
  2. filter (Store): Filter store

Example

import { createEvent, createStore, createApi, guard } from 'effector'
const trigger = createEvent()
const $unlocked = createStore(true)
const { lock, unlock } = createApi($unlocked, {
lock: () => false,
unlock: () => true,
})
const target = guard(trigger, {
filter: $unlocked,
})
target.watch(console.log)
trigger('A')
lock()
trigger('B') // nothing happens
unlock()
trigger('C')

Try it

guard(source, {filter: predicate})

Arguments

  1. source (Store/Event/Effect): Source unit. Will trigger given guard on updates
  2. filter ((payload) => Boolean): Predicate function, should be pure

Example 2

import { createEvent, guard } from 'effector'
const source = createEvent()
const target = guard(source, {
filter: (x) => x > 0,
})
target.watch(() => {
console.log('target called')
})
source(0)
// nothing happens
source(1)
// target called

Try it