### Install useEffectReducer package Source: https://context7.com/davidkpiano/useeffectreducer/llms.txt Command to install the library via npm. ```bash npm install use-effect-reducer ``` -------------------------------- ### Install and Import useEffectReducer Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md This snippet shows how to install the 'use-effect-reducer' package using npm and import the useEffectReducer hook into your React component. ```bash npm install use-effect-reducer ``` ```javascript import { useEffectReducer } from 'use-effect-reducer'; ``` -------------------------------- ### Replace Running Effects with exec.replace Source: https://context7.com/davidkpiano/useeffectreducer/llms.txt Shows how to atomically stop an existing effect and start a new one using exec.replace(). This pattern is ideal for debouncing inputs or updating effects with new parameters without race conditions. ```tsx case 'SEARCH': return { ...state, query: event.query, searchEffect: exec.replace(state.searchEffect, (_, __, dispatch) => { const controller = new AbortController(); fetch(`/api/search?q=${event.query}`, { signal: controller.signal }) .then((res) => res.json()) .then((data) => dispatch({ type: 'RESULTS', data })) .catch(() => {}); return () => { controller.abort(); }; }), }; ``` -------------------------------- ### Effect Implementation with Cleanup Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Provides an example of an effect implementation function. It shows how an effect can receive the current state, the effect object, and the dispatch function. It also demonstrates returning a cleanup function to handle side-effect disposal. ```javascript exec(() => { const id = setTimeout(() => { // do some delayed side-effect }, 1000); return () => { clearTimeout(id); }; }); ``` -------------------------------- ### useEffectReducer Hook API Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Presents the different ways to initialize the `useEffectReducer` hook. It can be used with an initial state and an effect reducer, or with an initialization function and an optional effects map for more complex setups. ```javascript const [state, dispatch] = useEffectReducer(effectReducer, initialState); const [state, dispatch] = useEffectReducer(effectReducer, initialState, effectsMap); const [state, dispatch] = useEffectReducer(effectReducer, initFunction, effectsMap); ``` -------------------------------- ### Named Effects with useEffectReducer Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Shows how to implement reusable effect reducers using named, parameterized effects. This example demonstrates fetching user data, where a 'fetchFromAPI' effect is dispatched and its implementation is provided as the third argument to useEffectReducer. ```javascript const fetchEffectReducer = (state, event, exec) => { switch (event.type) { case 'FETCH': exec({ type: 'fetchFromAPI', user: event.user }); return { ...state, status: 'fetching' }; case 'RESOLVE': return { status: 'fulfilled', user: event.data }; default: return state; } }; const Fetcher = () => { const [state, dispatch] = useEffectReducer( fetchEffectReducer, { status: 'idle', user: undefined }, { fetchFromAPI: (_, effect, dispatch) => { fetch(`/api/users/${effect.user}`) .then((res) => res.json()) .then((data) => { dispatch({ type: 'RESOLVE', data }); }); }, } ); // ... }; ``` -------------------------------- ### Replace Effects with exec.replace() Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Illustrates how to replace an existing effect with a new one using `exec.replace(entity, effect)`. This method stops the current effect and immediately starts a new one, returning a new effect entity. It's useful for scenarios like updating a timer or fetching new data based on user actions. ```javascript const timerReducer = (state, event, exec) => { if (event.type === 'START') { return { ...state, timer: exec(() => doSomeDelay()), }; } else if (event.type === 'LAP') { return { ...state, timer: exec.replace(state.timer, () => doSomeDelay()), }; } else if (event.type === 'STOP') { exec.stop(state.timer); return state; } return state; }; ``` -------------------------------- ### Stop Effects with exec.stop() Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Demonstrates how to explicitly stop a running effect using `exec.stop(entity)`. This is useful for managing side effects within a reducer, ensuring they are terminated when no longer needed. The reducer handles 'START' and 'STOP' events to control the effect. ```javascript const timerReducer = (state, event, exec) => { if (event.type === 'START') { return { ...state, timer: exec(() => { const id = setTimeout(() => { // delayed effect }, 1000); return () => clearTimeout(id); }), }; } else if (event.type === 'STOP') { exec.stop(state.timer); return state; } return state; }; ``` -------------------------------- ### Execute Initial Effects on Mount Source: https://context7.com/davidkpiano/useeffectreducer/llms.txt Explains how to trigger side effects immediately when a component mounts by providing an initializer function to useEffectReducer. The initializer receives the exec function to queue initial operations. ```tsx const getInitialState: InitialEffectStateGetter = (exec) => { exec({ type: 'fetchInitialData', endpoint: '/api/config' }); return { data: null, loading: true }; }; const ConfigLoader = () => { const [state] = useEffectReducer(dataReducer, getInitialState, { fetchInitialData(_, effect, dispatch) { fetch(effect.endpoint) .then((res) => res.json()) .then((data) => dispatch({ type: 'RESOLVE', data })) .catch(() => dispatch({ type: 'ERROR' })); return () => { console.log('Initial effect cleaned up'); }; }, }); // ... ``` -------------------------------- ### Queue effects with cleanup Source: https://context7.com/davidkpiano/useeffectreducer/llms.txt Demonstrates using the exec function to return an effect entity that includes a cleanup function, similar to the standard useEffect hook. ```tsx import { useEffectReducer, EffectEntity } from 'use-effect-reducer'; const timerReducer = (state: TimerState, event: TimerEvent, exec) => { switch (event.type) { case 'START': const entity = exec((currentState, effect, dispatch) => { const id = setInterval(() => { dispatch({ type: 'TICK' }); }, 1000); return () => { clearInterval(id); }; }); return { ...state, timerEntity: entity }; case 'TICK': return { ...state, count: state.count + 1 }; default: return state; } }; const Timer = () => { const [state, dispatch] = useEffectReducer(timerReducer, { count: 0 }); return (

Count: {state.count}

); }; ``` -------------------------------- ### Initial Effects with useEffectReducer Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Demonstrates how to provide initial effects when initializing the reducer. The second argument to useEffectReducer can be a function that receives `exec` and returns the initial state, allowing side-effects to run immediately upon component mount. ```javascript const getInitialState = (exec) => { exec({ type: 'fetchData', query: '*' }); return { data: null }; }; const [state, dispatch] = useEffectReducer(fetchReducer, getInitialState, { fetchData(_, { query }, dispatch) { fetch(`/api?${query}`) .then((res) => res.json()) .then((data) => dispatch({ type: 'RESOLVE', data })); }, }); ``` -------------------------------- ### Implement basic useEffectReducer hook Source: https://context7.com/davidkpiano/useeffectreducer/llms.txt Demonstrates the basic usage of useEffectReducer with an inline effect triggered by a state change. It returns the state and dispatch function similar to the standard React useReducer. ```tsx import { useEffectReducer } from 'use-effect-reducer'; const countReducer = (state, event, exec) => { switch (event.type) { case 'INC': exec(() => { console.log('Going up!'); }); return { ...state, count: state.count + 1 }; default: return state; } }; const Counter = () => { const [state, dispatch] = useEffectReducer(countReducer, { count: 0 }); return (
Count: {state.count}
); }; ``` -------------------------------- ### Define Typed Reducers and Effects with useEffectReducer Source: https://context7.com/davidkpiano/useeffectreducer/llms.txt Demonstrates how to define state, events, and effects using TypeScript interfaces and unions. It shows the implementation of a fully typed reducer and an effects map for managing asynchronous operations like data fetching. ```tsx import { useEffectReducer, EffectReducer, EffectsMap, EffectEntity, EffectReducerExec, InitialEffectStateGetter, } from 'use-effect-reducer'; interface AppState { status: 'idle' | 'loading' | 'success' | 'error'; data: string | null; fetchEntity?: EffectEntity; } type AppEvent = | { type: 'FETCH' } | { type: 'SUCCESS'; data: string } | { type: 'FAILURE' } | { type: 'CANCEL' }; type AppEffect = | { type: 'fetchData'; url: string } | { type: 'logAnalytics'; event: string }; const appReducer: EffectReducer = ( state, event, exec ) => { switch (event.type) { case 'FETCH': exec({ type: 'logAnalytics', event: 'fetch_started' }); return { ...state, status: 'loading', fetchEntity: exec({ type: 'fetchData', url: '/api/data' }), }; case 'SUCCESS': return { ...state, status: 'success', data: event.data }; case 'FAILURE': return { ...state, status: 'error', data: null }; case 'CANCEL': if (state.fetchEntity) exec.stop(state.fetchEntity); return { ...state, status: 'idle' }; default: return state; } }; const effectsMap: EffectsMap = { fetchData(state, effect, dispatch) { const controller = new AbortController(); fetch(effect.url, { signal: controller.signal }) .then((res) => res.json()) .then((data) => dispatch({ type: 'SUCCESS', data })) .catch(() => dispatch({ type: 'FAILURE' })); return () => controller.abort(); }, logAnalytics(state, effect) { console.log(`Analytics: ${effect.event}`, { state }); }, }; const App = () => { const [state, dispatch] = useEffectReducer( appReducer, { status: 'idle', data: null }, effectsMap ); return (

Status: {state.status}

); }; ``` -------------------------------- ### Basic useEffectReducer Usage in React Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Demonstrates a simple React component using useEffectReducer to manage a counter. It shows how to define a reducer function that handles events and dispatches actions, and how to integrate the hook into a functional component. ```javascript import { useEffectReducer } from 'use-effect-reducer'; const countReducer = (state, event, exec) => { switch (event.type) { case 'INC': exec(() => { console.log('Going up!'); }); return { ...state, count: state.count + 1, }; default: return state; } }; const App = () => { const [state, dispatch] = useEffectReducer(countReducer, { count: 0 }); return (
Count: {state.count}
); }; ``` -------------------------------- ### Dispatch String Events Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Shows how to dispatch events as simple strings when they do not require a payload. This simplifies event dispatching for basic actions, making the code more concise. It is equivalent to dispatching an object with a `type` property. ```javascript // Same as dispatch({ type: 'INC' }) dispatch('INC'); ``` -------------------------------- ### Stop Running Effects with exec.stop Source: https://context7.com/davidkpiano/useeffectreducer/llms.txt Demonstrates how to explicitly terminate a running effect by passing its entity to exec.stop(). This triggers the effect's cleanup function, useful for cancelling timers or pending operations. ```tsx const delayReducer = (state: DelayState, event: DelayEvent, exec) => { switch (event.type) { case 'START': return { ...state, message: 'Timer started...', timer: exec((_, __, dispatch) => { const id = setTimeout(() => { dispatch({ type: 'COMPLETE' }); }, 5000); return () => { clearTimeout(id); console.log('Timer cancelled'); }; }), }; case 'STOP': if (state.timer) { exec.stop(state.timer); } return { ...state, message: 'Timer stopped', timer: undefined }; // ... } }; ``` -------------------------------- ### Internal useEffectReducer Pattern Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Illustrates the underlying pattern that useEffectReducer abstracts. It shows how a traditional reducer might return both the next state and a list of effects, which are then handled by useEffect. ```javascript const myReducer = ([state], event) => { const effects = []; const exec = (effect) => effects.push(effect); const nextState = // calculate next state return [nextState, effects]; }; const [[state, effects], dispatch] = useReducer(myReducer); useEffect(() => { effects.forEach((effect) => { // execute the effect }); }, [effects]); ``` -------------------------------- ### Define named effects with effects map Source: https://context7.com/davidkpiano/useeffectreducer/llms.txt Shows how to separate effect logic from the reducer using an effects map. This approach improves testability and allows for complex side-effects like API calls. ```tsx import { useEffectReducer, EffectReducer } from 'use-effect-reducer'; const fetchReducer: EffectReducer = ( state, event, exec ) => { switch (event.type) { case 'FETCH': exec({ type: 'fetchFromAPI', user: event.user }); return { ...state, status: 'fetching' }; case 'RESOLVE': return { status: 'fulfilled', user: event.data }; default: return state; } }; const UserFetcher = () => { const [state, dispatch] = useEffectReducer( fetchReducer, { status: 'idle', user: undefined }, { fetchFromAPI(_, effect, dispatch) { fetch(`/api/users/${effect.user}`) .then((res) => res.json()) .then((data) => { dispatch({ type: 'RESOLVE', data }); }); }, } ); return (

Status: {state.status}

User: {state.user?.name || 'None'}

); }; ``` -------------------------------- ### exec(effect) Function Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Explains the `exec(effect)` function, which is used to queue an effect for execution. It accepts either an effect object or a function and returns an effect entity that can be used to control the effect's lifecycle. ```javascript const entity = exec({ type: 'alert', message: 'hello' }); // or inline: const entity = exec(() => alert('hello')); ``` -------------------------------- ### TypeScript Typing for Effect Reducer Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Demonstrates how to type an effect reducer using TypeScript generics `EffectReducer`. This provides type safety for the state, events, and effects handled by the reducer, improving code maintainability and reducing errors. ```typescript import { useEffectReducer, EffectReducer } from 'use-effect-reducer'; interface User { name: string; } type FetchState = | { status: 'idle'; user: undefined } | { status: 'fetching'; user: User | undefined } | { status: 'fulfilled'; user: User }; type FetchEvent = | { type: 'FETCH'; user: string } | { type: 'RESOLVE'; data: User }; type FetchEffect = { type: 'fetchFromAPI'; user: string; }; const fetchEffectReducer: EffectReducer< FetchState, FetchEvent, FetchEffect > = (state, event, exec) => { switch (event.type) { case 'FETCH': exec({ type: 'fetchFromAPI', user: event.user }); return { ...state, status: 'fetching' }; case 'RESOLVE': return { status: 'fulfilled', user: event.data }; default: return state; } }; ``` -------------------------------- ### Effect Entities for Effect Control Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Explains the concept of 'effect entities' returned by `exec(effect)`. These entities represent running effects and can be stored in the state to allow for later control, such as stopping or replacing the effect. ```javascript const someReducer = (state, event, exec) => { return { ...state, someEffect: exec(() => { /* ... */ }), }; }; ``` -------------------------------- ### exec.replace(entity, effect) Function Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Describes the `exec.replace(entity, effect)` function, which stops an existing effect and queues a new one in its place. This is useful for updating or changing side effects dynamically. It returns a new effect entity representing the replacement. ```javascript const newEntity = exec.replace(oldEntity, newEffect); ``` -------------------------------- ### exec.stop(entity) Function Source: https://github.com/davidkpiano/useeffectreducer/blob/master/README.md Details the `exec.stop(entity)` function, which stops a previously queued effect. It takes an effect entity as an argument and ensures that the effect's cleanup function is executed, preventing memory leaks and unintended side effects. ```javascript exec.stop(someEntity); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.