https://github.com/halaei/reducer-recipe
A redux reducer builder
https://github.com/halaei/reducer-recipe
Last synced: 7 days ago
JSON representation
A redux reducer builder
- Host: GitHub
- URL: https://github.com/halaei/reducer-recipe
- Owner: halaei
- Created: 2020-10-24T16:12:00.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2021-10-27T12:35:18.000Z (over 4 years ago)
- Last Synced: 2025-10-02T13:52:07.624Z (8 months ago)
- Language: JavaScript
- Size: 8.79 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: Readme.md
Awesome Lists containing this project
README
# Reducer recipe
`reducer-recipe` is an elegant CPU-efficient alternative to [combileReducers()](https://redux.js.org/api/combinereducers)
and [Redux Toolkit createReducer()](https://redux-toolkit.js.org/api/createreducer).
1. It lets you make faster reducers in an elegant code-style by avoiding large switch-case/if-else statements.
2. It provides a CPU-efficient way to combining a hierarchy of reducers into a single complex reducer.
According to the [benchmarks](./test/benchmark.test.js), using map of action types to small reducers that only handle
the give types, reducers generated by `reducer-recipe` are more CPU-efficient than the ones created by
`combileReducers()` or `createReducer()`.
## Recipes
A recipe is a function that takes a builder (r) as argument and gives r instructions on how it should generate the desired reducer.
To do so, recipe should call:
1. r.default(state): with the default value for state.
2. r.on(actionType, reducer(state, action)): to tell the builder how the final reducer should handle an action of given type.
```javascript
import builder from 'reducer-recipe';
const Artist = (r) => {
r.default({ name: 'Unknown', followers: 0, albums: [] })
.on('set-artist-name', (state, action) => {
return { ...state, name: action.name };
})
.on('set-artist-followers', (state, action) => {
return { ...state, followers: action.followers };
})
.on('publish-new-album', (state, action) => {
return { ...state, albums: [...state.albums, action.album] };
});
};
const artistReducer = builder.build(Artist);
```
The code above generates the following reducer:
```javascript
const artistReducer = (state = { name: 'Unknown', followers: 0, albums: [] }, action) => {
switch (action.type) {
case 'set-artist-name':
return { ...state, name: action.name };
case 'set-artist-followers':
return { ...state, followers: action.followers };
case 'publish-new-album':
return { ...state, albums: [...state.albums, action.album] };
default:
return state;
}
}
```
## Combine recipes and reducers
To make a bigger recipe from smaller recipes you can use `builder.combine()` function:
```javascript
const combinedRecipe = builder.combine({ Album, Artist});
const combinedReducer = builder.build(combinedRecipe);
```
Alternatively, you can call `builder.buildCombined()` to combine rececipes and build the reducer at once:
```javascript
const combinedReducer = builder.buildCombined({ Album, Artist});
```
If for some reason, you need pure reducers that cannot be built from recipes, and you want to mix them with recipes, you can pass them as second
argument to `builder.combine()` or `builder.buildCombined()`:
```javascript
const News = (state = [], action) => {
switch (action.type) {
case 'add-news':
return [action.news, ...state];
case 'pop-news':
let newState = [...state];
newState.pop();
return newState;
default:
return state;
}
};
const reducer = builder.buildCombined({ Album, Artist }, { News });
```
See [the tests file](./test/builder.test.js) to see a complete example.