Noiseless Praying Mantis

    redux-repository

    0.6.3 • Public • Published

    redux-repository

    npm CI CD Coverage Status

    A versatile set of pure functions to simplify the management of remote resources with Redux.

    • A single resource consists of:
      • ID
      • status: requested, received, failed
      • data, if the status is received
      • error, if the status is failed
      • timestamp of the data or error acquisition
    • The same resource can be requested from multiple places at the same time, it will only be fetched once
    • Resources are stored in the normalized state shape
    • Resources can be cached to skip consequent fetching
    • Read-only operations are supported so far: fetch and reset (remove local copy)

    Quick Start

    Install

    npm install redux-repository

    Use

    Implement action creators first:

    import { createFetchResource, createResetResources } from 'redux-repository/lib/actions';
    import { Action } from 'redux-repository/lib/types';
    import { ThunkAction } from 'redux-thunk';
    
    import { Product } from './Product';
    import { State } from './State';
    
    export interface FetchProductAction {
      (id: string): void;
    }
    
    export interface ResetProductsAction {
      (): void;
    }
    
    export const fetchProduct = (id: string): ThunkAction<void, State, null, Action<Product, string>> => (
      createFetchResource(
        'product',
        id,
        ({ catalog: { products } }) => products,
        (dispatchReceived, dispatchFailed) => {
          fetch(`https://example.com/api/products/${id}`)
            .then(response => response.json())
            .then(data => dispatchReceived(data))
            .catch(error => dispatchFailed(error.toString()));
        },
        {
          silentAlready: true, // skip "already received" messages, optional
          ttl: 60 * 1000, // cache for 1 minute, optional
        },
      )
    );
    
    export const resetProducts = (): ThunkAction<void, State, null, Action<Product, string>> => (
      createResetResources('product')
    );

    Then, inject the repository reducer:

    import { Action } from 'redux';
    import { isResourceAction, repositoryReducer } from 'redux-repository/lib/reducer';
    import { createInitialState } from 'redux-repository/lib/repository';
    import { Action as ReduxRepositoryAction } from 'redux-repository/lib/types';
    
    import { Product } from './Product';
    import { State } from './State';
    
    const initialState: State = {
      // ...
      catalog: {
        // ...
        products: createInitialState(),
      },
    };
    
    export default (state: State = initialState, action: Action): State => {
      if (isResourceAction('product', action as ReduxRepositoryAction<Product, string>)) {
        return {
          ...state,
          catalog: {
            ...state.catalog,
            products: repositoryReducer(state.catalog.products, action as ReduxRepositoryAction<Product, string>),
          },
        };
      }
    
      switch (action.type) {
        // ...
        default:
          return state;
      }
    };

    That's it! Now you can trigger fetchProduct, resetProducts and wire components to the repository via state:

    import { connect } from 'react-redux';
    import { Repository } from 'redux-repository/lib/interfaces';
    
    import { fetchProduct, FetchProductAction } from './actions';
    import { Product } from './Product';
    import { State } from './State';
    
    interface StateProps {
      products: Repository<Product, string>;
    }
    
    interface DispatchProps {
      fetchProduct: FetchProductAction;
    }
    
    const mapStateToProps = ({ catalog: { products } }: State): StateProps => ({ products });
    const mapDispatchToProps: DispatchProps = { fetchProduct };
    
    export const connect = connect(mapStateToProps, mapDispatchToProps);

    The full list of exported entities that might be useful:

    import {
      createFetchResource,
      createResetResources,
    } from 'redux-repository/lib/actions';
    
    import {
      RequestedResource,
      ReceivedResource,
      FailedResource,
      Resource,
      Repository,
    } from 'redux-repository/lib/interfaces';
    
    import {
      isResourceAction,
      repositoryReducer,
    } from 'redux-repository/lib/reducer';
    
    import {
      createInitialState,
      getResourceById,
      getResourcesArrayByIds,
      pushResource,
      pushResourcesArray,
      mergeRepositories,
    } from 'redux-repository/lib/repository';
    
    import {
      createFailed,
      createReceived,
      createRequested,
      extractData,
      extractError,
      isExpired,
      isFailed,
      isReceived,
      isRequested,
    } from 'redux-repository/lib/resource';
    
    import {
      Action,
    } from 'redux-repository/lib/types';
    
    // Examples:
    const productResource = getResourceById(productsRepository, productId);
    const productData = extractData(productResource);
    const productProgress = isRequested(productResource);

    Install

    npm i redux-repository

    DownloadsWeekly Downloads

    1

    Version

    0.6.3

    License

    MIT

    Unpacked Size

    40.2 kB

    Total Files

    20

    Last publish

    Collaborators

    • loginov-rocks