duck-magic

Utilities for Ducks - Modular Redux

Usage no npm install needed!

<script type="module">
  import duckMagic from 'https://cdn.skypack.dev/duck-magic';
</script>

README

duck-magic

Travis Prettier npm semantic-release License

Utilities for Ducks - Modular Redux

The library is a small set of utilities for managing ducks written to the Ducks Modular Redux design. However, to reduce the boilerplate, the interface for a "duck" when using this library is:

interface Duck<State> {
  reducer: (state: State, action) => State;
  actions: Record<string, Function>;
  selectors: Record<string, (state: State) => any>;
}

Install

With yarn:

yarn add duck-magic

With npm:

npm install --save duck-magic

Example

// ducks/math.js
const ADD = 'ADD';
const SUB = 'SUB';

export const reducer = (state = 0, { type, payload }) => {
  switch (type) {
    case ADD:
      return state + payload;
    case SUB:
      return state - payload;
    default:
      return state;
  }
};

export const actions = {
  add: value => ({ type: ADD, payload: value }),
  subtract: value => ({ type: SUB, payload: value }),
};

export const selectors = {
  isEven: state => state % 2 === 0,
  getValue: state => state,
};

Then in your index file:

// ducks/index.js
import {
  composeActionCreators,
  composeSelectors,
  createRootReducer,
} from 'duck-magic';

import * as math from './math';

const ducks = {
  math,
  // the rest of your ducks...
};

export const rootReducer = createRootReducer(ducks);
export const actions = composeActionCreators(ducks);
export const selectors = composeSelectors(ducks);

And finally, in your component:

import { connect } from 'react-redux';
import { selectors, actions } from '../ducks';

function Counter({ value, onAdd, onSubtract }) {
  // ...
}

const mapState = state => {
  value: selectors.math.getValue(state),
};
const mapDispatch = {
  onAdd: actions.math.add,
  onSubtract: actions.math.subtract,
};

export default connect(
  mapState,
  mapDispatch,
)(Counter);

API

composeActionCreators(ducks, [extraActionCreators])

Given an object containing ducks as values, returns another object whose values are the actions property of each duck.

composeSelectors(ducks, [extraSelectors])

Given an object containing ducks as values, returns another object whose values are the selectors property of each duck. The portion of state under the duck's key will be passed to the underlying selector.

createRootReducer(ducks, [extraReducers])

Given an object containing ducks as values, returns a function that is the result of calling Redux's combineReducers on all the reducers.