# redux-saga: Generator-Based Side Effect Management for Redux

> redux-saga is a Redux middleware that routes all asynchronous work, data fetching, and impure browser interactions through ES6 generator functions, making side effects testable without mocking and cancellable at any point. It treats each async workflow as a separate thread-like process that React actions can start, pause, or stop.

**redux-saga/redux-saga** — An alternative side effect model for Redux apps

- Repository: https://github.com/redux-saga/redux-saga
- Website: https://redux-saga.js.org/
- Stars: 22,415 · Forks: 1,932
- Language: JavaScript
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/redux-saga-redux-saga

## What Problem redux-saga Solves and Why Generators

redux-saga is a Redux middleware library that takes all application side effects, including data fetching and browser cache access, out of components and action creators and places them in a separate layer of generator functions called sagas. The README defines the mental model clearly: a saga is like a separate thread in the application that is solely responsible for side effects. That thread can be started, paused, and cancelled by dispatching ordinary Redux actions.

The library uses ES6 generators to write asynchronous flows in a style that looks like synchronous code. The README compares this to async/await but notes that generators have additional capabilities that redux-saga requires for features like task cancellation. The key practical benefit is testability: because generators yield descriptions of effects rather than executing them directly, tests can check those descriptions without running network requests or mocking browser APIs.

Before redux-saga, redux-thunk was the dominant approach. The README makes the distinction directly: unlike redux-thunk, sagas do not result in callback hell, asynchronous flows are easy to test, and action creators stay pure.

## Installing and Wiring the Middleware

Install the package from npm:

```sh
npm install redux-saga
```

Alternatively, using yarn:

```sh
yarn add redux-saga
```

Connecting redux-saga to a Redux store requires two steps: creating the middleware instance and then running a root saga. The README gives this setup in main.js:

```javascript
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'

import reducer from './reducers'
import mySaga from './sagas'

const sagaMiddleware = createSagaMiddleware()
const store = createStore(reducer, applyMiddleware(sagaMiddleware))

sagaMiddleware.run(mySaga)
```

The sagaMiddleware.run call starts the root saga. From that point, the saga can watch for dispatched actions and launch worker sagas in response. The store setup is otherwise identical to a Redux store without sagas.

## Writing a Worker Saga and Watching for Actions

The README's usage example shows a saga that fetches a user when a USER_FETCH_REQUESTED action is dispatched. The pattern uses takeEvery to watch for every matching action and fetchUser as the worker:

```javascript
import { call, put, takeEvery } from 'redux-saga/effects'
import Api from '...'

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

function* mySaga() {
  yield takeEvery('USER_FETCH_REQUESTED', fetchUser)
}
```

The call effect tells the middleware to call the function with the given arguments. The put effect dispatches an action to the store. The yield statements make each step observable in tests: a test can step through the generator, assert the yielded effect descriptor, and inject a result without touching the network.

takeEvery allows concurrent requests: if USER_FETCH_REQUESTED fires twice before the first completes, both worker sagas run in parallel. The alternative takeLatest automatically cancels any previous in-flight saga when a new matching action arrives, which is useful for search boxes or form submissions where only the most recent request matters.

## Browser Usage via UMD Build

For projects without a module bundler, redux-saga ships UMD builds in the dist/ folder. When loaded via a script tag, the middleware is available as ReduxSaga in the window object:

```javascript
var sagaMiddleware = ReduxSaga.default()
```

The README provides direct URLs through unpkg for both the development and minified builds. There is an important browser compatibility requirement: if the target browser does not support ES2015 generators natively, the code must be transpiled using a Babel plugin such as regenerator-transform, and a regenerator runtime must be imported before redux-saga:

```javascript
import 'regenerator-runtime/runtime'
import sagaMiddleware from 'redux-saga'
```

The README recommends the UMD path only for environments without webpack or Browserify. Projects using a modern bundler should use the npm package and let the bundler handle tree-shaking and transpilation.

## Running the Bundled Examples

The repository includes several examples adapted from the original Redux example set. To build and run them from source:

```sh
git clone https://github.com/redux-saga/redux-saga.git
cd redux-saga
pnpm install
pnpm test
```

The README lists three counter examples at different complexity levels. The counter-vanilla example uses plain JavaScript and the UMD build, runnable by opening its index.html directly in a browser with Generator support. The counter example uses webpack and the high-level takeEvery API. The cancellable-counter example demonstrates low-level task cancellation using the fork and cancel effects.

Additional examples cover a shopping cart, an async pattern, and a real-world example with webpack hot reloading. Each example has a corresponding npm run command documented in the README.

## TypeScript Support and Compatibility Requirements

The README notes that using redux-saga with TypeScript requires including either DOM.Iterable or ES2015.Iterable in the TypeScript configuration's lib array. For a tsconfig with target set to ES6, this is typically already satisfied. For ES5 targets, the iterable type definitions must be added explicitly to avoid type errors on generator return types.

The package publishes a separate @redux-saga/types package, which the monorepo workspace tracks alongside the core. The most recent release of @redux-saga/types (1.4.1) was published on the same date as the core 1.5.1 release, indicating they are versioned together.

One limitation worth noting: sagas are built on generators, which transpile to more verbose state machines in older JavaScript targets. For mobile applications or embedded environments where bundle size is a hard constraint, the generated output size from transpiled generators can be a meaningful factor when choosing between redux-saga and simpler approaches like redux-thunk or the thunk middleware built into Redux Toolkit.

## When redux-saga Is the Wrong Tool

The README does not address use cases where simpler alternatives fit better, but the library's own complexity makes the boundary visible. redux-saga introduces generator syntax, a new vocabulary of effects (call, put, fork, take, race, all), and a separate testing strategy that differs from component and reducer testing. For a project with only a handful of API calls and no need for cancellation or sequencing, that overhead is real.

Redux Toolkit ships a built-in createAsyncThunk helper and RTK Query for server state management. These tools handle common patterns like loading states, error handling, and cache management without generators. The README explicitly positions redux-saga as an alternative to redux-thunk, but for projects starting fresh today, the choice is more often between redux-saga and RTK Query rather than between redux-saga and plain thunks.

redux-saga also has no built-in integration with React's Suspense model. Coordinating saga-driven async workflows with Suspense requires custom bridging code.

## Conclusion

redux-saga is the right choice for Redux applications with complex async sequences: multi-step workflows, request cancellation, race conditions, or operations that must run in parallel and then join. Projects with straightforward data fetching and no need for cancellation or complex coordination will find the generator overhead unnecessary. Before adopting it, check whether your TypeScript tsconfig includes DOM.Iterable or ES2015.Iterable, since the README requires one of those for type compatibility.

## FAQ

### What is a saga in Redux?

In redux-saga, a saga is a generator function that runs as a separate thread-like process alongside the application, handling all side effects such as data fetching and browser cache access. It listens for dispatched Redux actions and responds by running async workflows.

### What are the key differences between Redux Saga and Redux Thunk?

The README states that unlike redux-thunk, redux-saga avoids callback hell, makes async flows easy to test, and keeps action creators pure. Redux-saga uses generators with yielded effect descriptors, while redux-thunk uses functions that directly call dispatch.

### What is yield in redux-saga?

yield is the ES6 generator keyword that redux-saga uses to pause a saga and hand control to the middleware. The yielded value is an effect descriptor, such as call() or put(), that tells the middleware what action to perform next.

### Is redux-saga still used?

The repository shows active maintenance, with the most recent release at version 1.5.1 published on 2026-07-26. The library continues to receive updates, though many projects starting fresh today use Redux Toolkit's built-in async utilities instead.

### How do I use redux-saga with Redux Toolkit?

The README does not document Redux Toolkit integration directly. In practice, adding the saga middleware follows the same configureStore setup described in Redux Toolkit's documentation, using getDefaultMiddleware or middleware option to inject createSagaMiddleware().

## Sources

- [License: MIT](https://github.com/redux-saga/redux-saga/blob/main/LICENSE)
- [Project website](https://redux-saga.js.org/)
- [README](https://github.com/redux-saga/redux-saga/blob/main/README.md)
- [redux-saga/redux-saga on GitHub](https://github.com/redux-saga/redux-saga)
- [Releases](https://github.com/redux-saga/redux-saga/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/redux-saga-redux-saga
