Saga middleware for Redux to handle side effects using ES6 generators
—
Core effects for the most common saga operations: waiting for actions, dispatching actions, calling functions, and accessing state.
Creates an effect that instructs the middleware to wait for a specified action on the Store. The generator is suspended until an action matching the pattern is dispatched.
/**
* Wait for a specified action on the Store
* @param pattern - Action pattern to match (string, function, array, or undefined for all)
* @returns TakeEffect that resolves with the matched action
*/
function take<A extends Action>(pattern?: ActionPattern<A>): TakeEffect;
/**
* Wait for message from a channel
* @param channel - Channel to take from
* @param multicastPattern - Optional pattern for multicast channels
* @returns ChannelTakeEffect that resolves with the message
*/
function take<T>(
channel: TakeableChannel<T>,
multicastPattern?: Pattern<T>
): ChannelTakeEffect<T>;Usage Examples:
import { take } from "redux-saga/effects";
function* watchActions() {
// Take any action
const action = yield take();
// Take specific action type
const loginAction = yield take('LOGIN_REQUEST');
// Take multiple action types
const authAction = yield take(['LOGIN_REQUEST', 'LOGOUT_REQUEST']);
// Take with predicate function
const userAction = yield take(action => action.type.startsWith('USER_'));
}Same as take() but does not automatically terminate the saga on an END action. Instead, sagas blocked on takeMaybe will receive the END object.
/**
* Like take() but doesn't terminate on END actions
* @param pattern - Action pattern to match
* @returns TakeEffect that can receive END without terminating
*/
function takeMaybe<A extends Action>(pattern?: ActionPattern<A>): TakeEffect;
function takeMaybe<T>(
channel: TakeableChannel<T>,
multicastPattern?: Pattern<T>
): ChannelTakeEffect<T>;Creates an effect that instructs the middleware to dispatch an action to the Store. This effect is non-blocking and errors bubble back into the saga.
/**
* Dispatch an action to the Store (non-blocking)
* @param action - Action object to dispatch
* @returns PutEffect
*/
function put<A extends Action>(action: A): PutEffect<A>;
/**
* Put action into a channel
* @param channel - Channel to put into
* @param action - Message to put
* @returns ChannelPutEffect
*/
function put<T>(channel: PuttableChannel<T>, action: T | END): ChannelPutEffect<T>;Usage Examples:
import { put } from "redux-saga/effects";
function* loginSaga(action) {
try {
const user = yield call(api.login, action.payload);
// Dispatch success action
yield put({ type: 'LOGIN_SUCCESS', user });
} catch (error) {
// Dispatch error action
yield put({ type: 'LOGIN_FAILURE', error: error.message });
}
}Just like put() but the effect is blocking (waits for promise resolution if returned from dispatch) and will bubble up errors from downstream.
/**
* Dispatch an action to the Store (blocking, waits for resolution)
* @param action - Action object to dispatch
* @returns PutEffect that waits for dispatch completion
*/
function putResolve<A extends Action>(action: A): PutEffect<A>;Creates an effect that instructs the middleware to call a function with arguments. Handles Promises, Generator functions, and synchronous values.
/**
* Call a function with arguments
* @param fn - Function to call (can be generator, async, or sync)
* @param args - Arguments to pass to the function
* @returns CallEffect that resolves with the function result
*/
function call<Fn extends (...args: any[]) => any>(
fn: Fn,
...args: Parameters<Fn>
): CallEffect<SagaReturnType<Fn>>;
/**
* Call method on context object
* @param ctxAndFnName - Array of [context, methodName]
* @param args - Arguments to pass to the method
* @returns CallEffect
*/
function call<Ctx extends { [P in Name]: (this: Ctx, ...args: any[]) => any }, Name extends string>(
ctxAndFnName: [Ctx, Name],
...args: Parameters<Ctx[Name]>
): CallEffect<SagaReturnType<Ctx[Name]>>;
/**
* Call with context and function as object properties
* @param ctxAndFnName - Object with context and fn properties
* @param args - Arguments to pass
* @returns CallEffect
*/
function call<Ctx extends { [P in Name]: (this: Ctx, ...args: any[]) => any }, Name extends string>(
ctxAndFnName: { context: Ctx; fn: Name },
...args: Parameters<Ctx[Name]>
): CallEffect<SagaReturnType<Ctx[Name]>>;Usage Examples:
import { call } from "redux-saga/effects";
function* fetchUserSaga(action) {
// Call async function
const user = yield call(fetch, `/api/users/${action.payload.id}`);
const userData = yield call([user, 'json']);
// Call with context
const result = yield call([api, 'getUser'], action.payload.id);
// Call generator function
const processed = yield call(processUserData, userData);
}Alias for call([context, fn], ...args). Convenient way to call methods on objects.
/**
* Call method on object (alias for call([context, fn], ...args))
* @param ctx - Context object
* @param fnName - Method name
* @param args - Arguments array
* @returns CallEffect
*/
function apply<Ctx extends { [P in Name]: (this: Ctx, ...args: any[]) => any }, Name extends string>(
ctx: Ctx,
fnName: Name,
args: Parameters<Ctx[Name]>
): CallEffect<SagaReturnType<Ctx[Name]>>;Creates an effect that instructs the middleware to invoke a function as a Node-style function (with callback as last parameter).
/**
* Call Node-style function with callback
* @param fn - Function that takes callback as last parameter
* @param args - Arguments to pass before callback
* @returns CpsEffect
*/
function cps<Fn extends (...args: any[]) => any>(
fn: RequireCpsCallback<Fn>,
...args: CpsFunctionParameters<Fn>
): CpsEffect<ReturnType<Fn>>;
interface CpsCallback<R> {
(error: any, result: R): void;
cancel?(): void;
}Usage Examples:
import { cps } from "redux-saga/effects";
import fs from "fs";
function* readFileSaga() {
try {
// Call Node-style fs.readFile
const content = yield cps(fs.readFile, 'config.json', 'utf8');
console.log('File content:', content);
} catch (error) {
console.error('Failed to read file:', error);
}
}Creates an effect that instructs the middleware to invoke a selector on the current Store's state.
/**
* Get current state or run selector on state
* @param selector - Optional selector function
* @param args - Additional arguments for selector
* @returns SelectEffect that resolves with selected state
*/
function select(): SelectEffect;
function select<Fn extends (state: any, ...args: any[]) => any>(
selector: Fn,
...args: Tail<Parameters<Fn>>
): SelectEffect;Usage Examples:
import { select } from "redux-saga/effects";
// Selectors
const getUser = (state) => state.user;
const getUserById = (state, id) => state.users.find(u => u.id === id);
function* userSaga() {
// Get entire state
const state = yield select();
// Use selector
const user = yield select(getUser);
// Selector with arguments
const specificUser = yield select(getUserById, 123);
}Creates an effect that blocks execution for specified milliseconds and optionally returns a value.
/**
* Block execution for specified milliseconds
* @param ms - Milliseconds to delay
* @param val - Optional value to return after delay
* @returns CallEffect that resolves after delay
*/
function delay<T = true>(ms: number, val?: T): CallEffect<T>;Usage Examples:
import { delay } from "redux-saga/effects";
function* pollingSaga() {
while (true) {
yield call(fetchData);
// Wait 5 seconds before next poll
yield delay(5000);
}
}
function* timeoutSaga() {
// Delay with custom return value
const result = yield delay(1000, 'timeout complete');
console.log(result); // 'timeout complete'
}Creates an effect that instructs the middleware to return a specific property from the saga's context object.
/**
* Get a property from the saga's context
* @param prop - Property name to retrieve from context
* @returns GetContextEffect that resolves with the context property value
*/
function getContext(prop: string): GetContextEffect;Usage Examples:
import { getContext } from "redux-saga/effects";
function* authSaga() {
// Get API client from context
const apiClient = yield getContext('apiClient');
// Get user session
const session = yield getContext('session');
// Use context values
const user = yield call([apiClient, 'getCurrentUser'], session.token);
}Creates an effect that instructs the middleware to update the saga's context object with new properties.
/**
* Update the saga's context with new properties
* @param props - Object containing properties to merge into context
* @returns SetContextEffect
*/
function setContext(props: object): SetContextEffect;Usage Examples:
import { setContext, getContext } from "redux-saga/effects";
function* setupSaga() {
// Initialize context
yield setContext({
apiClient: new ApiClient(),
retryCount: 0
});
// Update retry count later
const currentRetryCount = yield getContext('retryCount');
yield setContext({ retryCount: currentRetryCount + 1 });
}Install with Tessl CLI
npx tessl i tessl/npm-redux-saga