Create reducers from simple declarative data models
The motivation behind redux-toolkit is to enable simple intuitive reducer composition and avoid boilerplate code. A reducer is a simple functional building block which makes it endlessly composable. However, handwriting traditional redux reducers can be verbose and cumbersome. Instead redux-remodel lets you declare a reducer as a model with actions, computed properties, and sub-models (i.e. slices). The resulting reducer function is also decorated with action creators for convenient action dispatching.
Under the hood redux-remodel uses Immer so you can write mutative actions and still preserve reducer purity and state immutability. Using Immer also enables structural sharing which reduces the memory intensity of traditional redux reducers. Action creators are built with createAction()
from @reduxjs/toolkit and computed properties rely on the Reselect utility.
npm install --save redux-remodel
Define a todos model
const todos = {
actions: {
addTodo: (todos, { payload }) => {
todos.push({ id: todos.length + 1, title: payload });
},
toggleTodo: (todos, { payload }) => {
const todo = todos.find((t) => t.id === payload.id);
if (todo) {
todo.completed = !todo.completed;
}
}
}
};
Declare a new model by composing todos
import { createModel } from 'redux-remodel';
const initialState = { view: 'all' };
const app = createModel(initialState, {
slices: {
todos: createModel([], todos)
},
actions: {
setView: (state, { payload: view }) => {
state.view = view;
}
},
computed: {
active: ({ todos }) => todos.filter((t) => !t.completed),
completed: ({ todos }) => todos.filter((t) => t.completed),
visibleTodos: (state) => {
switch (state.view) {
case 'ACTIVE':
return state.active;
case 'COMPLETED':
return state.completed;
default:
return state.todos;
}
}
}
});
Use like a reducer function
let state;
state = app(state, { type: 'addTodo', payload: 'My Todo' });
console.log(state);
/*
{
view: 'all',
todos: [{ id: 1, title: 'My Todo' }],
active: [{ id: 1, title: 'My Todo' }],
completed: []
}
*/
The returned reducer is decorated with action creators
app(state, app.actions.addTodo('My Todo'))
MIT © gingerich