@ftw/redux-utils

State management utilities for Redux.

Stats

stars 🌟issues ⚠️updated 🛠created 🐣size 🏋️‍♀️
@ftw/redux-utils
Minified + gzip package size for @ftw/redux-utils in KB

Readme

FTW Redux Utils

State management utilities for Redux.

⚠️ Definitely a WIP ⚠️

Operations

The simplest Operation is just an action type and a reducer:

import { createOperation } from '@ftw/redux-utils';

const increment = createOperation({
  actionType: 'INCREMENT',
  reducer: state => state + 1
});

You can customize the action creator if you want:

import { createOperation } from '@ftw/redux-utils';

const increment = Operation({
  actionType: 'INCREMENT',
  actionCreator: amount => ({ payload: { amount } }),
  reducer: (state, action) => state + action.payload.amount
});

Asynchronous Operations

Sometimes an Operation needs to handle some asynchronous logic (e.g. making a request to your API and then storing the response). This is almost as simple to write as a synchronous operation:

import { createAsyncOperation } from '@ftw/redux-utils';

const fetchArticles = createAsyncOperation({
  actionType: 'FETCH_ARTICLES',
  reducer: (state, action) => {
    switch (action.status) {
      case 'pending': {
        return {
          ...state,
          fetchStatus: 'pending'
        };
      }

      case 'success': {
        return {
          ...state,
          fetchStatus: 'success',
          articles: action.payload.data
        };
      }

      case 'error': {
        return {
          ...state,
          fetchStatus: 'error'
        };
      }
    }

    return state;
  },
  perform: () => axios.get('/api/articles').then(({ data }) => data)
});

Modules

Operations can be composed into a Module. A Module contains the reducer, saga, action creators, and selectors for a specific "slice" of your application state.

Here's a counter Module with an initial state of 0:

import { createModule, createOperation } from '@ftw/redux-utils';

const Counter = createModule({
  initialState: 0,
  operations: {
    increment: createOperation({
      actionType: 'INCREMENT',
      reducer: state => state + 1
    }),
    decrement: createOperation({
      actionType: 'DECREMENT',
      reducer: state => state - 1
    })
  },
  selectors: {
    getState: state => state
  }
})('counter');

The created module has the following API:

Counter.reducer(state, action);
Counter.saga();
Counter.actions.increment();
Counter.actions.decrement();
Counter.selectors.getState(state);

If you find any bugs or have a feature request, please open an issue on github!

The npm package download data comes from npm's download counts api and package details come from npms.io.