0.0.3 • Published 7 years ago
@ftw/redux-utils v0.0.3
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);