https://github.com/azz/duck-magic
Utilities for Ducks - Modular Redux
https://github.com/azz/duck-magic
ducks redux
Last synced: about 2 months ago
JSON representation
Utilities for Ducks - Modular Redux
- Host: GitHub
- URL: https://github.com/azz/duck-magic
- Owner: azz
- License: mit
- Created: 2018-10-19T12:50:10.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-10-20T02:17:42.000Z (over 7 years ago)
- Last Synced: 2025-10-20T06:17:10.718Z (8 months ago)
- Topics: ducks, redux
- Language: JavaScript
- Size: 94.7 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# `duck-magic`
[](https://travis-ci.org/azz/duck-magic)
[](https://github.com/prettier/prettier)
[](https://npmjs.org/duck-magic)
[](https://github.com/semantic-release/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](https://github.com/erikras/ducks-modular-redux)** design. However, to reduce the boilerplate, the interface for a "duck" when using this library is:
```ts
interface Duck {
reducer: (state: State, action) => State;
actions: Record;
selectors: Record any>;
}
```
## Install
With `yarn`:
```shellsession
yarn add duck-magic
```
With `npm`:
```shellsession
npm install --save duck-magic
```
## Example
```js
// 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:
```js
// 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:
```js
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 `reducer`s.