### Install typed-redux-saga Source: https://github.com/agiledigital/typed-redux-saga/blob/master/README.md Instructions for installing the typed-redux-saga package using either yarn or npm. This package requires TypeScript 3.6 or later. ```shell # yarn yarn add typed-redux-saga # npm npm install typed-redux-saga ``` -------------------------------- ### Install Babel Macro for typed-redux-saga Source: https://github.com/agiledigital/typed-redux-saga/blob/master/README.md Instructions for installing the `babel-plugin-macros` dependency, which is used to automatically transform typed-redux-saga effects into raw redux-saga effects during compilation. ```shell yarn add --dev babel-plugin-macros ``` -------------------------------- ### Using typed-redux-saga with Babel Macro Source: https://github.com/agiledigital/typed-redux-saga/blob/master/README.md Demonstrates how to import effects from `typed-redux-saga/macro` and how these imports are transpiled to standard `redux-saga/effects` imports at compile time. This allows for strong typing during development without runtime overhead. ```javascript import {call, race} from "typed-redux-saga/macro"; // And use the library normally function* myEffect() { yield* call(() => "foo"); } ``` ```javascript import {call, race} from "redux-saga/effects"; function* myEffect() { yield call(() => 'foo'); } ``` -------------------------------- ### Redux Saga Usage: Before and After Typed Redux Saga Source: https://github.com/agiledigital/typed-redux-saga/blob/master/README.md Compares the usage of `call` and `all` effects in redux-saga before and after adopting typed-redux-saga. The 'After' version demonstrates how typed-redux-saga provides stronger type inference for effect results and uses `yield*` for effect execution. ```typescript import { call, all } from "redux-saga/effects"; // Let's assume Api.fetchUser() returns Promise // Api.fetchConfig1/fetchConfig2 returns Promise, Promise import Api from "..."; function* fetchUser(action) { // `user` has type any const user = yield call(Api.fetchUser, action.payload.userId); ... } function* fetchConfig() {} // `result` has type any const result = yield all({ api1: call(Api.fetchConfig1), api2: call(Api.fetchConfig2), }); ... ``` ```typescript // Note we import `call` from typed-redux-saga import { call, all } from "typed-redux-saga"; // Let's assume Api.fetchUser() returns Promise // Api.fetchConfig1/fetchConfig2 returns Promise, Promise import Api from "..."; function* fetchUser(action) { // Note yield is replaced with yield* // `user` now has type User, not any! const user = yield* call(Api.fetchUser, action.payload.userId); ... } function* fetchConfig() {} // Note yield is replaced with yield* // `result` now has type {api1: Config1, api2: Config2} const result = yield* all({ api1: call(Api.fetchConfig1), api2: call(Api.fetchConfig2), }); ... ``` -------------------------------- ### Action Watching with takeEvery, takeLatest, takeLeading in typed-redux-saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Details the takeEvery, takeLatest, and takeLeading helper effects in typed-redux-saga for handling dispatched actions. These effects provide different strategies for managing concurrent sagas triggered by actions, ensuring proper typing. ```typescript import { takeEvery, takeLatest, takeLeading, call, put } from "typed-redux-saga"; interface FetchUserAction { type: "FETCH_USER"; payload: { userId: number }; } async function fetchUserApi(id: number): Promise<{ id: number; name: string }> { const response = await fetch(`/api/users/${id}`); return response.json(); } // Worker saga with typed action function* fetchUserWorker(action: FetchUserAction) { const user = yield* call(fetchUserApi, action.payload.userId); yield* put({ type: "FETCH_USER_SUCCESS", payload: user }); } function* watchFetchUser() { // Responds to every FETCH_USER action yield* takeEvery("FETCH_USER", fetchUserWorker); } function* watchFetchUserLatest() { // Cancels previous saga if new action arrives yield* takeLatest("FETCH_USER", fetchUserWorker); } function* watchFetchUserLeading() { // Ignores new actions while saga is running yield* takeLeading("FETCH_USER", fetchUserWorker); } ``` -------------------------------- ### Fork and Spawn Tasks with typed-redux-saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Demonstrates how to create attached (fork) and detached (spawn) tasks using typed-redux-saga. Forked tasks are managed by the parent and can be cancelled, while spawned tasks run independently. Both return typed Task objects. ```typescript import { fork, spawn, join, cancel } from "typed-redux-saga"; import type { SagaGenerator } from "typed-redux-saga"; function* backgroundSync(): SagaGenerator { let count = 0; while (true) { yield* call(syncData); count++; } return count; } function* mainSaga() { // task is typed as FixedTask const task = yield* fork(backgroundSync); // Wait for some condition yield* take("STOP_SYNC"); // Cancel the task yield* cancel(task); // Spawn a detached task (won't be cancelled if parent is cancelled) const detachedTask = yield* spawn(function* () { yield* call(cleanupResources); return "done"; }); // Join waits for task completion and returns the result // result is typed as "done" const result = yield* join(detachedTask); } ``` -------------------------------- ### Action Channel and Flush Utilities in Typed Redux Saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Illustrates `actionChannel` and `flush` for managing and processing actions in Redux Saga. `actionChannel` creates a channel to buffer actions, while `flush` retrieves all currently buffered items from a channel. ```typescript import { actionChannel, take, flush, call, delay } from "typed-redux-saga"; import { buffers } from "redux-saga"; interface RequestAction { type: "REQUEST"; payload: { id: number }; } function* watchRequests() { // Create a buffered channel for REQUEST actions // channel is typed as Channel const requestChannel = yield* actionChannel( "REQUEST", buffers.sliding(10) ); while (true) { // Take from channel - action is typed as RequestAction const action = yield* take(requestChannel); yield* call(handleRequest, action.payload.id); } } function* flushExample() { const channel = yield* actionChannel("REQUEST"); // Process accumulated requests yield* delay(5000); // Flush returns all buffered items - typed as RequestAction[] const bufferedRequests = yield* flush(channel); console.log(`Processing ${bufferedRequests.length} buffered requests`); } ``` -------------------------------- ### Babel Macro for Zero-Runtime Overhead in Typed Redux Saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Details the usage of the `typed-redux-saga/macro` path with Babel to achieve zero-runtime overhead in production. This macro transforms typed effects back to raw Redux Saga effects during compilation, maintaining type safety during development. ```typescript // Install babel-plugin-macros // yarn add --dev babel-plugin-macros // Import from the macro path instead import { call, take, all, race } from "typed-redux-saga/macro"; // Use exactly the same way - types work during development function* myEffect() { const result = yield* call(() => "foo"); const action = yield* take("SOME_ACTION"); const combined = yield* all({ one: call(() => 1), two: call(() => 2) }); } // After babel compilation, the above becomes: // import { call, take, all, race } from "redux-saga/effects"; // function* myEffect() { // const result = yield call(() => "foo"); // const action = yield take("SOME_ACTION"); // const combined = yield all({ // one: call(() => 1), // two: call(() => 2) // }); // } ``` -------------------------------- ### SetContext and GetContext Utilities in Typed Redux Saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Explains how to use `setContext` and `getContext` for sharing data across sagas in a type-safe manner. `setContext` establishes shared values, while `getContext` retrieves them in child sagas. ```typescript import { setContext, getContext, fork } from "typed-redux-saga"; interface SagaContext { apiClient: { baseUrl: string }; logger: { log: (msg: string) => void }; } function* initializeSaga() { // Set context values yield* setContext({ apiClient: { baseUrl: "/api" }, logger: { log: console.log } }); yield* fork(childSaga); } function* childSaga() { // Get typed context value const apiClient = yield* getContext("apiClient"); console.log(apiClient.baseUrl); // Type safe const logger = yield* getContext("logger"); logger.log("Child saga started"); // Type safe } ``` -------------------------------- ### Take Effect with Typed Redux Saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Shows the 'take' and 'takeMaybe' effects in Typed Redux Saga for waiting on specific actions or channel messages. It provides type safety for received actions and messages. ```typescript import { take, takeMaybe } from "typed-redux-saga"; import { channel } from "redux-saga"; interface LoginAction { type: "LOGIN"; payload: { username: string; password: string }; } interface LogoutAction { type: "LOGOUT"; } function* authFlow() { while (true) { // TypeScript infers loginAction as LoginAction const loginAction = yield* take("LOGIN"); console.log(`User ${loginAction.payload.username} logging in`); // Wait for logout const logoutAction = yield* take("LOGOUT"); } } // Using with channels function* channelExample() { const chan = channel<{ data: string }>(); // msg is typed as { data: string } const msg = yield* take(chan); console.log(msg.data); } ``` -------------------------------- ### Delay and Retry Utilities in Typed Redux Saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Demonstrates the use of `delay` and `retry` effects from typed-redux-saga for managing asynchronous operations and handling failures with retries. `delay` pauses execution, optionally returning a value, while `retry` attempts an operation multiple times with a delay. ```typescript import { delay, retry, call } from "typed-redux-saga"; async function unreliableApi(): Promise<{ status: string }> { if (Math.random() > 0.5) { throw new Error("Random failure"); } return { status: "success" }; } function* delayExample() { // Default returns true after delay const done = yield* delay(1000); // done is typed as true // Can return custom value const result = yield* delay(1000, "custom-value"); // result is typed as "custom-value" } function* retryExample() { // Retry up to 5 times with 1 second delay between attempts // result is typed as { status: string } const result = yield* retry(5, 1000, unreliableApi); console.log(result.status); } ``` -------------------------------- ### Select Effect with Typed Redux Saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Demonstrates the 'select' effect in Typed Redux Saga for accessing the Redux store state. It ensures type safety for selectors and their return values. ```typescript import { select } from "typed-redux-saga"; interface RootState { users: { currentUser: { id: number; name: string } | null; list: Array<{ id: number; name: string }>; }; settings: { theme: "light" | "dark"; }; } // Typed selector function const selectCurrentUser = (state: RootState) => state.users.currentUser; const selectUserById = (state: RootState, userId: number) => state.users.list.find(u => u.id === userId); function* userSaga() { // currentUser is correctly typed as { id: number; name: string } | null const currentUser = yield* select(selectCurrentUser); if (currentUser) { console.log(currentUser.name); } // With additional arguments const user = yield* select(selectUserById, 123); // user is typed as { id: number; name: string } | undefined } ``` -------------------------------- ### Rate Limiting with throttle and debounce in typed-redux-saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Demonstrates the use of 'throttle' and 'debounce' effects in typed-redux-saga for controlling the frequency of saga executions. Throttle limits execution to at most once per specified interval, while debounce waits for a pause in actions before executing. ```typescript import { throttle, debounce, call, put } from "typed-redux-saga"; interface SearchAction { type: "SEARCH"; payload: { query: string }; } async function searchApi(query: string): Promise { const response = await fetch(`/api/search?q=${query}`); return response.json(); } function* searchWorker(action: SearchAction) { const results = yield* call(searchApi, action.payload.query); yield* put({ type: "SEARCH_SUCCESS", payload: results }); } function* rootSaga() { // Execute at most once every 500ms yield* throttle(500, "SEARCH", searchWorker); } function* rootSagaDebounced() { // Wait 300ms after last action before executing yield* debounce(300, "SEARCH", searchWorker); } ``` -------------------------------- ### Parallel Execution with 'all' in typed-redux-saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Illustrates using the 'all' effect in typed-redux-saga to run multiple effects concurrently. It supports both array and object forms, returning combined results with type safety. This is useful for fetching related data simultaneously. ```typescript import { all, call } from "typed-redux-saga"; async function fetchUser(id: number): Promise<{ id: number; name: string }> { return { id, name: "User" }; } async function fetchSettings(): Promise<{ theme: string }> { return { theme: "dark" }; } async function fetchNotifications(): Promise { return ["notification1", "notification2"]; } function* loadDashboard() { // Array form - result is typed as [{ id: number; name: string }, { theme: string }, string[]] const [user, settings, notifications] = yield* all([ call(fetchUser, 1), call(fetchSettings), call(fetchNotifications) ]); // Object form - result is typed as { user: {...}, settings: {...}, notifications: string[] } const result = yield* all({ user: call(fetchUser, 1), settings: call(fetchSettings), notifications: call(fetchNotifications) }); console.log(result.user.name); // Type safe console.log(result.settings.theme); // Type safe } ``` -------------------------------- ### Call Effect with Typed Redux Saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Demonstrates the 'call' effect in Typed Redux Saga for invoking functions, including API calls and methods with context binding. It ensures proper type inference for function results. ```typescript import { call } from "typed-redux-saga"; // API function that returns a Promise async function fetchUser(userId: number): Promise<{ id: number; name: string }> { const response = await fetch(`/api/users/${userId}`); return response.json(); } function* fetchUserSaga(userId: number) { // TypeScript correctly infers user as { id: number; name: string } const user = yield* call(fetchUser, userId); console.log(user.name); // Full type safety return user; } // With context binding const api = { baseUrl: "/api", async getUser(id: number): Promise<{ id: number; name: string }> { const response = await fetch(`${this.baseUrl}/users/${id}`); return response.json(); } }; function* fetchWithContext() { // Using tuple syntax for context binding const user = yield* call([api, api.getUser], 123); // Or using object syntax const user2 = yield* call({ context: api, fn: "getUser" }, 456); return { user, user2 }; } ``` -------------------------------- ### Put Effect with Typed Redux Saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Illustrates the 'put' effect in Typed Redux Saga for dispatching actions with type preservation. It ensures that dispatched actions conform to their defined interfaces. ```typescript import { put } from "typed-redux-saga"; interface FetchUserSuccessAction { type: "FETCH_USER_SUCCESS"; payload: { id: number; name: string }; } interface FetchUserErrorAction { type: "FETCH_USER_ERROR"; error: string; } function* handleUserFetch() { try { const user = { id: 1, name: "John" }; // Returns the dispatched action with proper type const action = yield* put({ type: "FETCH_USER_SUCCESS", payload: user }); // action is typed as FetchUserSuccessAction } catch (error) { yield* put({ type: "FETCH_USER_ERROR", error: String(error) }); } } ``` -------------------------------- ### Race Conditions with 'race' in typed-redux-saga Source: https://context7.com/agiledigital/typed-redux-saga/llms.txt Explains the 'race' effect in typed-redux-saga, which runs multiple effects in parallel and resolves as soon as the first one completes. The result object contains properties for each effect, with only the winning effect's result being defined. ```typescript import { race, call, take, delay } from "typed-redux-saga"; async function fetchData(): Promise<{ data: string }> { return { data: "fetched" }; } function* fetchWithTimeout() { // Object form - result has properties that may be undefined const result = yield* race({ data: call(fetchData), timeout: delay(5000), cancelled: take("CANCEL_FETCH") }); // result is typed as { data: { data: string } | undefined; timeout: true | undefined; cancelled: ... | undefined } if (result.data) { console.log("Fetch succeeded:", result.data.data); } else if (result.timeout) { console.log("Fetch timed out"); } else if (result.cancelled) { console.log("Fetch was cancelled"); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.