or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

basic-effects.mdchannels.mdconcurrency-effects.mdhelper-effects.mdindex.mdmiddleware.mdtesting.mdutilities.md
tile.json

tessl/npm-redux-saga

Saga middleware for Redux to handle side effects using ES6 generators

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/redux-saga@1.3.x

To install, run

npx @tessl/cli install tessl/npm-redux-saga@1.3.0

index.mddocs/

Redux-Saga

Redux-Saga is a library that makes application side effects (asynchronous things like data fetching and impure things like accessing the browser cache) easier to manage, more efficient to execute, easy to test, and better at handling failures. It uses ES6 generator functions to make asynchronous flows easy to read, write and test, creating a mental model where sagas act as separate threads solely responsible for side effects.

Package Information

  • Package Name: redux-saga
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install redux-saga

Core Imports

import createSagaMiddleware from "redux-saga";
import { take, put, call, fork, select } from "redux-saga/effects";

For CommonJS:

const createSagaMiddleware = require("redux-saga").default;
const { take, put, call, fork, select } = require("redux-saga/effects");

Basic Usage

import { createStore, applyMiddleware } from "redux";
import createSagaMiddleware from "redux-saga";
import { take, put, call, fork } from "redux-saga/effects";

// Create saga middleware
const sagaMiddleware = createSagaMiddleware();

// Apply middleware to store
const store = createStore(
  reducer,
  applyMiddleware(sagaMiddleware)
);

// Example saga
function* fetchUserSaga(action) {
  try {
    const user = yield call(Api.fetchUser, action.payload.userId);
    yield put({ type: 'USER_FETCH_SUCCEEDED', user });
  } catch (e) {
    yield put({ type: 'USER_FETCH_FAILED', message: e.message });
  }
}

function* watchFetchUser() {
  yield take('USER_FETCH_REQUESTED', fetchUserSaga);
}

// Start the saga
sagaMiddleware.run(watchFetchUser);

Architecture

Redux-Saga is built around several key concepts:

  • Generator Functions: ES6 generators that can be paused and resumed, making async code look synchronous
  • Effects: Plain JavaScript objects that describe what the saga should do (declarative)
  • Middleware: Redux middleware that connects sagas to the Redux store
  • Tasks: Objects representing running generator functions that can be cancelled or joined
  • Channels: Communication mechanism between sagas and external event sources

Capabilities

Middleware Creation

Core functionality for creating and configuring the Redux middleware that connects sagas to your Redux store.

interface SagaMiddlewareOptions<C extends object = {}> {
  context?: C;
  sagaMonitor?: SagaMonitor;
  onError?(error: Error, errorInfo: ErrorInfo): void;
  effectMiddlewares?: EffectMiddleware[];
  channel?: MulticastChannel<Action>;
}

interface SagaMiddleware<C extends object = {}> extends Middleware {
  run<S extends Saga>(saga: S, ...args: Parameters<S>): Task;
  setContext(props: Partial<C>): void;
}

function createSagaMiddleware<C extends object>(
  options?: SagaMiddlewareOptions<C>
): SagaMiddleware<C>;

Middleware

Basic Effects

Core effects for the most common saga operations: waiting for actions, dispatching actions, calling functions, and managing context.

function take<A extends Action>(pattern?: ActionPattern<A>): TakeEffect;

function put<A extends Action>(action: A): PutEffect<A>;

function call<Fn extends (...args: any[]) => any>(
  fn: Fn,
  ...args: Parameters<Fn>
): CallEffect<SagaReturnType<Fn>>;

function select<Fn extends (state: any, ...args: any[]) => any>(
  selector?: Fn,
  ...args: Tail<Parameters<Fn>>
): SelectEffect;

function getContext(prop: string): GetContextEffect;

function setContext(props: object): SetContextEffect;

Basic Effects

Concurrency Effects

Effects for managing concurrent execution, forking tasks, and coordinating multiple asynchronous operations.

function fork<Fn extends (...args: any[]) => any>(
  fn: Fn,
  ...args: Parameters<Fn>
): ForkEffect<SagaReturnType<Fn>>;

function spawn<Fn extends (...args: any[]) => any>(
  fn: Fn,
  ...args: Parameters<Fn>
): ForkEffect<SagaReturnType<Fn>>;

function join(task: Task): JoinEffect;

function cancel(task: Task): CancelEffect;

function all<T>(effects: T[]): AllEffect<T>;

function race<T>(effects: { [key: string]: T }): RaceEffect<T>;

Concurrency Effects

Helper Effects

High-level helper effects built on top of basic effects for common patterns like handling every action, latest action, or throttling.

function takeEvery<P extends ActionPattern>(
  pattern: P,
  worker: (action: ActionMatchingPattern<P>) => any
): ForkEffect<never>;

function takeLatest<P extends ActionPattern>(
  pattern: P,
  worker: (action: ActionMatchingPattern<P>) => any
): ForkEffect<never>;

function takeLeading<P extends ActionPattern>(
  pattern: P,
  worker: (action: ActionMatchingPattern<P>) => any
): ForkEffect<never>;

function throttle<P extends ActionPattern>(
  ms: number,
  pattern: P,
  worker: (action: ActionMatchingPattern<P>) => any
): ForkEffect<never>;

function debounce<P extends ActionPattern>(
  ms: number,
  pattern: P,
  worker: (action: ActionMatchingPattern<P>) => any
): ForkEffect<never>;

Helper Effects

Channels

Channel system for communication between sagas and external event sources, enabling integration with WebSockets, DOM events, and other async data sources.

function channel<T extends NotUndefined>(buffer?: Buffer<T>): Channel<T>;

function eventChannel<T extends NotUndefined>(
  subscribe: Subscribe<T>,
  buffer?: Buffer<T>
): EventChannel<T>;

function multicastChannel<T extends NotUndefined>(): MulticastChannel<T>;

function actionChannel(
  pattern: ActionPattern,
  buffer?: Buffer<Action>
): ActionChannelEffect;

Channels

Testing Utilities

Tools for testing sagas in isolation, including cloneable generators and mock tasks.

function cloneableGenerator<S extends Saga>(
  saga: S
): (...args: Parameters<S>) => SagaIteratorClone;

function createMockTask(): MockTask;

Testing

Utility Functions

General utility functions for working with Redux-Saga effects and values.

function detach<T>(forkEffect: ForkEffect<T>): ForkEffect<T>;
function isEnd(value: any): value is END;

Utility Packages

Additional utility packages providing type checking, symbols, deferred promises, and monitoring capabilities.

// Type checking utilities
import * as is from "@redux-saga/is";

// Symbol constants
import { CANCEL, SAGA_ACTION, TASK } from "@redux-saga/symbols";

// Deferred promises
import deferred from "@redux-saga/deferred";

// Promise-based delay
import delay from "@redux-saga/delay-p";

// Saga monitoring
import createSagaMonitor from "@redux-saga/simple-saga-monitor";

Utilities

Types

Core Types

interface Action<T extends string = string> {
  type: T;
}

interface AnyAction extends Action {
  [extraProps: string]: any;
}

interface Task {
  isRunning(): boolean;
  result<T = any>(): T | undefined;
  error(): any | undefined;
  toPromise<T = any>(): Promise<T>;
  cancel(): void;
  setContext(props: object): void;
}

type ActionPattern<A extends Action = Action> =
  | string
  | string[]
  | ((action: A) => boolean)
  | A['type'][];

type NotUndefined = {} | null;

interface Saga<Args extends any[] = any[], Return = any> {
  (...args: Args): SagaIterator<Return>;
}

interface SagaIterator<T = any> extends Iterator<any, T, any> {
  readonly name: string;
}

interface Buffer<T> {
  isEmpty(): boolean;
  put(message: T): void;
  take(): T | undefined;
}

interface TakeableChannel<T> {
  take(cb: (message: T | END) => void): void;
}

interface PuttableChannel<T> {
  put(message: T | END): void;
}

interface FlushableChannel<T> {
  flush(cb: (items: T[] | END) => void): void;
}

interface Channel<T> extends TakeableChannel<T>, PuttableChannel<T>, FlushableChannel<T> {
  close(): void;
}

interface MulticastChannel<T> extends Channel<T> {
  take(cb: (message: T | END) => void, matcher?: Predicate<T>): void;
}

type Predicate<T> = (value: T) => boolean;
type END = { type: 'END' };
type EndType = END;

Effect Types

type TakeEffect = SimpleEffect<'TAKE', TakeEffectDescriptor>;
type PutEffect<A extends Action = AnyAction> = SimpleEffect<'PUT', PutEffectDescriptor<A>>;
type CallEffect<RT = any> = SimpleEffect<'CALL', CallEffectDescriptor<RT>>;
type ForkEffect<RT = any> = SimpleEffect<'FORK', ForkEffectDescriptor<RT>>;
type SelectEffect = SimpleEffect<'SELECT', SelectEffectDescriptor>;
type GetContextEffect = SimpleEffect<'GET_CONTEXT', GetContextEffectDescriptor>;
type SetContextEffect = SimpleEffect<'SET_CONTEXT', SetContextEffectDescriptor>;
type AllEffect<T> = CombinatorEffect<'ALL', T>;
type RaceEffect<T> = CombinatorEffect<'RACE', T>;

interface SimpleEffect<T, P> {
  type: T;
  payload: P;
}

interface CombinatorEffect<T, P> {
  type: T;
  payload: P;
}

type ActionMatchingPattern<P> = P extends string 
  ? Action<P>
  : P extends (action: infer A) => boolean 
    ? A extends Action ? A : Action
    : Action;

type SagaReturnType<S extends Function> = S extends (...args: any[]) => SagaIterator<infer RT>
  ? RT
  : S extends (...args: any[]) => Promise<infer RT>
  ? RT
  : S extends (...args: any[]) => infer RT
  ? RT
  : never;

type Tail<L extends any[]> = L extends [any, ...infer T] ? T : never;

Constants

/** Symbol used for cancellation */
const CANCEL: string;

/** Special action type that terminates sagas */
const END: EndType;

/** Effect type constants */
const effectTypes: {
  TAKE: 'TAKE';
  PUT: 'PUT';
  ALL: 'ALL';
  RACE: 'RACE';
  CALL: 'CALL';
  CPS: 'CPS';
  FORK: 'FORK';
  JOIN: 'JOIN';
  CANCEL: 'CANCEL';
  SELECT: 'SELECT';
  ACTION_CHANNEL: 'ACTION_CHANNEL';
  CANCELLED: 'CANCELLED';
  FLUSH: 'FLUSH';
  GET_CONTEXT: 'GET_CONTEXT';
  SET_CONTEXT: 'SET_CONTEXT';
};