0.0.0 • Published 6 years ago

atomic-redux v0.0.0

Weekly downloads
-
License
MIT
Repository
-
Last release
6 years ago

Atomic Redux

Build Status npm version Coverage Status

This library cuts down on boilerplate of writing reducers and action-creators for collection-based state. The goal is to make it easier to create and work with normalized state trees.

The idea behind atomic Redux is to limit a collection reducer to basic or "atomic" operations - set, add, remove, and replace. For example:

const itemsReducer = (items = [], { type, payload }) => {
  switch (type) {
    case 'SET_ITEMS': return payload.items;
    case 'ADD_ITEM': return addItemToItems(payload.item, items)
    case 'REMOVE_ITEM': return removeItemFromItems(payload.itemId, items)
    case 'REPLACE_ITEM': return replaceItemInItems(payload.item, items)
    default: return items
  }
}

Each atomic operation gets an action creator:

const setItems = items => ({ type: 'SET_ITEMS', payload: items })
const addItem = (id, item) => ({ type: 'ADD_ITEM', payload: { id, item } })
const removeItem = id => ({ type: 'REMOVE_ITEM', payload: id })
const replaceItem = (id, item) => ({ type: 'REPLACE_ITEM', payload: { id, item } })

Then, you can combine atomic action creators to make complex action creators:

// with redux-thunk
const upsertItem = (item) => {
  return dispatch => {
    const action = item.id ? replaceItem(item.id, item) : addItem(item);
    dispatch(action);
  }
}

As shown, atomic reducer operations provide some nice benefits:

  • an easy API to define how a collection state reduces
  • simple and closed set of reductions = no accidental state mutation
  • clear separation between state management and "business logic"
  • no need to write hairy object manipulation code in the reducer

This library comes into play by providing a utility function to create an atomic reducer and its action creators. And if you keep each collection flat, they can be associated through foreign-key-like identifier fields, similar to a relational database, and you will have achieved a normalized Redux state.

Installation

yarn add atomic-redux

Usage

Two utility functions are provided:

  • createArrayModule: use this if your collection substate is an array
  • createObjectModule: use this if your collection substate is an object-literal (key-value map)

createArrayModule

Use this if your collection substate is an array.

import { createArrayModule } from 'atomic-redux';
import types from './actionTypes';

const { reducer, actionCreators } = createArrayModule({
  setAction:     types.SET_CHICKENS,
  addAction:     types.ADD_CHICKEN,
  removeAction:  types.REMOVE_CHICKEN,
  replaceAction: types.REPLACE_CHICKEN,
});

It will return 4 action creators:

const { setItems, addItem, removeItem, replaceItem } = actionCreators;

Assign them to variables with appropriate names for your use case:

const setChickens = actionCreators.setItem;
const addChicken = actionCreators.addItem;
const removeChicken = actionCreators.removeItem;
const replaceChicken = actionCreators.replaceItem;

And then use them like this:

setChickens([
    { id: 1, name: 'Beeky' },
    { id: 2, name: 'Bert' }
]);

addChicken({ id: 3, name: 'Wingz' })

removeChicken(2);

replaceChicken(1, { id: 1, name: 'Nuggy' })

createObjectModule

Use this if your collection substate is an object-literal (key-value map)

import { createObjectModule } from 'atomic-redux';
import types from './actionTypes';

const { reducer, actionCreators } = createObjectModule({
  setAction:     types.SET_CHICKENS,
  addAction:     types.ADD_CHICKEN,
  removeAction:  types.REMOVE_CHICKEN,
  replaceAction: types.REPLACE_CHICKEN,
});

It will return 4 action creators:

const { setItems, addItem, removeItem, replaceItem } = actionCreators;

Assign them to variables with appropriate names for your use case:

const setChickens = actionCreators.setItem;
const addChicken = actionCreators.addItem;
const removeChicken = actionCreators.removeItem;
const replaceChicken = actionCreators.replaceItem;

And then use them like this:

setChickens({
    1: { id: 1, name: 'Beeky' },
    2: { id: 2, name: 'Bert' }
});

addChicken(3, { id: 3, name: 'Wingz' })

removeChicken(2);

replaceChicken(1, { id: 1, name: 'Nuggy' })

Options

Custom key for array-based state items: In createArrayModule, by default, the replace and remove operations will look for id as the key on each object. To change this, pass a callback to the utility function:

const { reducer, actionCreators } = createArrayModule({
    // ...
    getKey: item => item.myCustomId
});
0.0.0

6 years ago

0.3.3

6 years ago

0.3.2

6 years ago

0.3.1

6 years ago