{"id":17465,"library":"redux-saga","title":"Redux Saga","description":"Redux-Saga is a middleware library for Redux, designed to manage application side effects (like asynchronous data fetching, accessing the browser cache, or impure actions) in a more organized and testable manner. It leverages ES6 Generators to make asynchronous flows look like synchronous code, improving readability and maintainability. The current stable version is 1.4.2, with patch releases occurring relatively frequently and minor versions every few months. Its key differentiators include its declarative effect model, powerful concurrency control patterns (e.g., `takeEvery`, `takeLatest`), and robust testing utilities, providing a structured alternative to Redux Thunk for complex side effect management.","status":"active","version":"1.4.2","language":"javascript","source_language":"en","source_url":"https://github.com/redux-saga/redux-saga#main","tags":["javascript","redux","middleware","saga","effects","side effects","typescript"],"install":[{"cmd":"npm install redux-saga","lang":"bash","label":"npm"},{"cmd":"yarn add redux-saga","lang":"bash","label":"yarn"},{"cmd":"pnpm add redux-saga","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required as a peer dependency for integrating the saga middleware into a Redux store.","package":"redux","optional":false}],"imports":[{"note":"This is the default export of the main `redux-saga` package.","wrong":"import { createSagaMiddleware } from 'redux-saga';","symbol":"createSagaMiddleware","correct":"import createSagaMiddleware from 'redux-saga';"},{"note":"Effect creators like `takeEvery`, `put`, `call`, `all` are imported from the `redux-saga/effects` submodule, not the main package.","wrong":"import { takeEvery } from 'redux-saga';","symbol":"takeEvery","correct":"import { takeEvery, put, call } from 'redux-saga/effects';"},{"note":"TypeScript types should be imported using `import type` for clarity and to avoid runtime issues if the type name clashes with a value.","wrong":"import { Saga } from 'redux-saga';","symbol":"Saga","correct":"import type { Saga } from 'redux-saga';"}],"quickstart":{"code":"import { createStore, applyMiddleware } from 'redux';\nimport createSagaMiddleware from 'redux-saga';\nimport { takeEvery, put, call } from 'redux-saga/effects';\n\n// Reducer\nconst counterReducer = (state = { count: 0 }, action) => {\n  switch (action.type) {\n    case 'INCREMENT':\n      return { count: state.count + 1 };\n    case 'DECREMENT':\n      return { count: state.count - 1 };\n    default:\n      return state;\n  }\n};\n\n// Sagas\nfunction* incrementAsync() {\n  yield call(delay, 1000); // Simulate an async operation\n  yield put({ type: 'INCREMENT' });\n}\n\nfunction* delay(ms) {\n  return new Promise(res => setTimeout(res, ms));\n}\n\nfunction* rootSaga() {\n  yield takeEvery('INCREMENT_ASYNC', incrementAsync);\n}\n\n// Create saga middleware\nconst sagaMiddleware = createSagaMiddleware();\n\n// Create Redux store\nconst store = createStore(\n  counterReducer,\n  applyMiddleware(sagaMiddleware)\n);\n\n// Run sagas\nsagaMiddleware.run(rootSaga);\n\n// Dispatch actions\nstore.dispatch({ type: 'INCREMENT_ASYNC' });\nstore.dispatch({ type: 'INCREMENT' });\n\n// Log state changes\nstore.subscribe(() => console.log(store.getState()));\n","lang":"typescript","description":"This quickstart sets up a basic Redux store with `redux-saga` middleware. It demonstrates defining a simple counter reducer, creating an asynchronous saga using generator functions and effect creators (`call`, `put`, `takeEvery`), and running the saga with `sagaMiddleware.run()`."},"warnings":[{"fix":"Ensure all imports are from the official public entry points (e.g., `redux-saga` or `redux-saga/effects`). Avoid importing directly from deep paths like `redux-saga/lib/utils/someInternalFile`.","message":"The `exports` field was added to `package.json` in v1.4.0. This change restricts what files can be directly imported from the package. While public APIs are maintained, any prior deep imports to non-public files might break.","severity":"breaking","affected_versions":">=1.4.0"},{"fix":"For `redux-saga@1.4.1+`, ensure `moduleResolution` is set appropriately, typically to `bundler` or `node`. If issues persist, review the `redux-saga` GitHub issues for specific `tsconfig.json` recommendations for your setup.","message":"When using TypeScript, incorrect `moduleResolution` settings in `tsconfig.json` (e.g., 'bundler' or 'node') can lead to type compatibility issues, especially with older versions or specific bundler configurations.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Consult the official `redux-saga` migration guide for detailed steps and breaking changes when upgrading from `0.x` to `1.x`.","message":"Prior to v1.0.0, the API for `createSagaMiddleware` and effect creators had different signatures and argument orders. Migrating from older `0.x` versions requires careful review of the migration guide.","severity":"breaking","affected_versions":"<1.0.0 to 1.x"},{"fix":"Ensure `sagaMiddleware.run(rootSaga)` is called only once when initializing your application. If you need to restart or hot-reload sagas, consider using `sagaMiddleware.run(saga, ...args).toPromise()` to manage saga lifecycle.","message":"Using `sagaMiddleware.run()` multiple times with the same saga instance can lead to unintended behavior, as the saga will be started again. It's typically meant to be called once per root saga.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Change your import statement to `import createSagaMiddleware from 'redux-saga';` instead of `import { createSagaMiddleware } from 'redux-saga';`.","cause":"`createSagaMiddleware` is typically a default export from `redux-saga`.","error":"TypeError: createSagaMiddleware is not a function"},{"fix":"Ensure the saga function passed to `takeEvery` is declared as a generator function, e.g., `function* myWorkerSaga() { yield put({ type: 'ACTION' }); }`.","cause":"The second argument passed to `takeEvery` (or similar effect creators) must be a generator function (e.g., `function* mySaga() { ... }`).","error":"Error: takeEvery(pattern, saga): saga argument must be a Generator function!"},{"fix":"Verify that `redux-saga` is correctly installed. Check your `tsconfig.json`'s `compilerOptions.moduleResolution` (e.g., try 'bundler' or 'node') and ensure `node_modules/@redux-saga/types` is accessible. Upgrading to `redux-saga@1.4.1` or newer might also help if you are on an older version with this issue.","cause":"This error often indicates incorrect `moduleResolution` in `tsconfig.json` or issues with package installation/bundler configuration, preventing TypeScript from finding the submodule types.","error":"TS2307: Cannot find module 'redux-saga/effects' or its corresponding type declarations."},{"fix":"Inside a saga, always `yield` effect creators from `redux-saga/effects` (e.g., `yield call(api.fetchData)` or `yield put({ type: 'ACTION' })`). Do not use `await` directly; use `yield call` for promise-based functions.","cause":"This error occurs when you use `await` or return a Promise directly from a saga without yielding an effect, or if you're not yielding a proper `redux-saga` effect object.","error":"effects must be plain objects, received [object Promise]"}],"ecosystem":"npm","meta_description":null}