Glossary of basic terms in effector.

Event

Event is a function you can subscribe to. It can be an intention to change the store, indication of something happening in the application, a command to be executed, aggregated analytics trigger and so on.

Event in api documentation

Store

Store is an object that holds state. There can be multiple stores.

Store in api documentation

Effect

Effect is a container for (possibly async) side effects. It exposes special events and stores, such as .pending, .done, .fail, .finally, etc…

It can be safely used in place of the original async function.

It returns promise with the result of a function call.

The only requirement for the function:

  • Must have zero or one argument

Effect in api documentation

Domain

Domain is a namespace for your events, stores and effects.

Domains are notified when events, stores, effects, or nested domains are created via .onCreateEvent, .onCreateStore, .onCreateEffect, .onCreateDomain methods.

It is useful for logging or other side effects.

Domain in api documentation

Unit

Data type used to describe business logic of applications. Most of the effector methods deal with unit processing. There are five unit types: Store, Event, Effect, Domain and Scope.

Common unit

Common units can be used to trigger updates of other units. There are three common unit types: Store, Event and Effect. When a method accepts units, it means that it accepts events, effects, and stores as a source of reactive updates.

Purity

Most of the functions in api must not call other events or effects: it’s easier to reason about application’s data flow when imperative triggers are grouped inside watchers and effect handlers rather than spread across entire business logic.

Correct, imperative:

import { createStore, createEvent } from "effector";

const submitLoginSize = createEvent();

const $login = createStore("guest");
const $loginSize = $login.map((login) => login.length);

$loginSize.watch((size) => {
  submitLoginSize(size);
});

Try it

Reference: Store.map, Store.watch

Better, declarative:

import { createStore, createEvent, sample } from "effector";

const submitLoginSize = createEvent();

const $login = createStore("guest");
const $loginSize = $login.map((login) => login.length);

sample({
  clock: $loginSize,
  target: submitLoginSize,
});

Try it

Reference: sample

Incorrect:

import { createStore, createEvent } from "effector";

const submitLoginSize = createEvent();

const $login = createStore("guest");
const $loginSize = $login.map((login) => {
  // no! use `sample` instead
  submitLoginSize(login.length);
  return login.length;
});

Reducer

type StoreReducer<State, E> = (state: State, payload: E) => State | void;
type EventOrEffectReducer<T, E> = (state: T, payload: E) => T;

Reducer calculates a new state given the previous state and an event’s payload. For stores, if reducer returns undefined or the same state (===), then there will be no update for a given store.

Watcher

type Watcher<T> = (update: T) => any;

Watcher is used for side effects. Accepted by Event.watch, Store.watch and Domain.onCreate* hooks. Return value of a watcher is ignored.

Subscription

import { type Subscription } from "effector";

Looks like:

type Subscription = {
  (): void;
  unsubscribe(): void;
};

Function, returned by forward, Event.watch, Store.watch and some other methods. Used for cancelling a subscription. After the first call, subscription will do nothing.

warning

Managing subscriptions manually distracts from business logic improvements.

Effector provides a wide range of features to minimize the need to remove subscriptions. This sets it apart from most other reactive libraries.

Contributors