Norwegian Parcel Mail

    use-reducer-async
    TypeScript icon, indicating that this package has built-in type declarations

    2.1.1 • Public • Published

    use-reducer-async

    CI npm size discord

    React useReducer with async actions

    Introduction

    React useReducer doesn't support async actions natively. Unlike Redux, there's no middleware interface, but hooks are composable.

    This is a tiny library to extend useReducer's dispatch so that dispatching async actions invoke async functions.

    Install

    npm install use-reducer-async

    Usage

    import { useReducerAsync } from "use-reducer-async";
    
    const initialState = {
      sleeping: false,
    };
    
    const reducer = (state, action) => {
      switch (action.type) {
        case 'START_SLEEP': return { ...state, sleeping: true };
        case 'END_SLEEP': return { ...state, sleeping: false };
        default: throw new Error('no such action type');
      }
    };
    
    const asyncActionHandlers = {
      SLEEP: ({ dispatch }) => async (action) => {
        dispatch({ type: 'START_SLEEP' });
        await new Promise(r => setTimeout(r, action.ms));
        dispatch({ type: 'END_SLEEP' });
      },
    };
    
    const Component = () => {
      const [state, dispatch] = useReducerAsync(reducer, initialState, asyncActionHandlers);
      return (
        <div>
          <span>{state.sleeping ? 'Sleeping' : 'Idle'}</span>
          <button type="button" onClick={() => dispatch({ type: 'SLEEP', ms: 1000 })}>Click</button>
        </div>
      );
    };

    Notes for abortability

    All async action handlers receive signal in the argument. Refer examples/04_abort/src for the usage.

    Note: The implementation depends on AbortController in the DOM spec. If you are using an environment that doesn't have AbortController (for example IE11), you need a polyfill: 1 2

    API

    useReducerAsync

    useReducer with async actions

    Parameters

    • reducer R
    • initialState ReducerState<R>
    • asyncActionHandlers AsyncActionHandlers<R, AsyncAction>

    Examples

    import { useReducerAsync } from 'use-reducer-async';
    
    const asyncActionHandlers = {
      SLEEP: ({ dispatch, getState, signal }) => async (action) => {
        dispatch({ type: 'START_SLEEP' });
        await new Promise(r => setTimeout(r, action.ms));
        dispatch({ type: 'END_SLEEP' });
      },
      FETCH: ({ dispatch, getState, signal }) => async (action) => {
        dispatch({ type: 'START_FETCH' });
        try {
          const response = await fetch(action.url);
          const data = await response.json();
          dispatch({ type: 'FINISH_FETCH', data });
        } catch (error) {
          dispatch({ type: 'ERROR_FETCH', error });
        }
      },
    };
    const [state, dispatch] = useReducerAsync(reducer, initialState, asyncActionHandlers);

    Returns [ReducerState<R>, Dispatch<ExportAction>]

    Examples

    The examples folder contains working examples. You can run one of them with

    PORT=8080 npm run examples:01_minimal

    and open http://localhost:8080 in your web browser.

    You can also try them in codesandbox.io: 01 02 03 04

    Install

    npm i use-reducer-async

    DownloadsWeekly Downloads

    4,953

    Version

    2.1.1

    License

    MIT

    Unpacked Size

    34.3 kB

    Total Files

    12

    Last publish

    Collaborators

    • daishi