A small, simple and immutable model to manage data in your Redux store.
After multiple project with react and redux, the file structure begin unmaintainable, constants on one side, reducers on another. I tried to put everything in a file but I end up with a large file. So I created for my needs, a bookstore allowing me to have maintainable and clear code I was inspired by react-redux and react-ORM
npm install --save redux-way
import { Model } from 'redux-way';
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const RESET = 'RESET';
export default class CounterModel extends Model {
// Used to resolve all related store
static modelName = 'counter';
// Initial state
static state = 0;
// Differents actions related to the model
static actions = {
increment: () => ({type: INCREMENT}),
decrement: () => ({type: DECREMENT}),
reset: () => ({type: RESET})
};
// Reducer linked by constants
reducer = {
[INCREMENT]: (state, action, model) => {model.update(state + 1)},
[DECREMENT]: (state, action, model) => {model.update(state - 1)},
[RESET]: (state, action, model) => {model.update(0)}
};
}
import { createStore } from 'redux';
import { Register } from 'redux-way';
import { CounterModel } from './model';
const register = new Register();
// Register your models
register.register(CounterModel);
const store = createStore(createReducer(register));
import React from 'react';
import { CounterModel } from './models';
import { connect } from 'redux-way';
export class Counter extends React.Component{
render() {
const { counter, decrement, increment, reset } = this.props;
return (
<div>
{counter}
<br />
<button onClick={decrement}>Decrement</button>
<button onClick={increment}>Incremente</button>
<button onClick={reset}>Reset</button>
</div>
)
}
}
// Same api as react-redux
const mapStateToProps = (state) => {
return { counter: state.counter }
}
const mapDispatchToProps = {
increment: CounterModel.actions.increment,
decrement: CounterModel.actions.decrement,
reset: CounterModel.actions.reset,
}
export default connect(mapStateToProps, mapDispatchToProps)(Counter)
import { createStore } from 'redux';
import { Register } from 'redux-way';
import createSagaMiddleware from 'redux-saga'
import { CounterModel } from './model';
const sagaMiddleware = createSagaMiddleware()
const register = new Register();
// Register your models
register.register(CounterModel);
const store = createStore(createReducer(register));
// register sagaMiddleware, launch after store has been created
register.sagaMiddleware(sagaMiddleware);
import { Model } from 'redux-way';
import {delay} from 'redux-saga'
import {put, takeEvery} from 'redux-saga/effects'
export const INCREMENT = 'INCREMENT';
export const ASYNC_INCREMENT = 'ASYNC_INCREMENT';
export const DECREMENT = 'DECREMENT';
export const RESET = 'RESET';
export default class CounterModel extends Model {
// Used to resolve all related store
static modelName = 'counter';
// Initial state
static state = 0;
// Differents actions related to the model
static actions = {
increment: () => ({type: INCREMENT}),
asyncIncrement: () => ({type: ASYNC_INCREMENT}),
decrement: () => ({type: DECREMENT}),
reset: () => ({type: RESET})
};
// launch by sagaMiddleware.run
run = function* () {
yield takeEvery(ASYNC_INCREMENT, this.changeName)
}
changeName = function* () {
yield delay(1000);
yield put({type: INCREMENT})
}
// Reducer linked by constants
reducer = {
[INCREMENT]: (state, action, model) => {model.update(state + 1)},
[DECREMENT]: (state, action, model) => {model.update(state - 1)},
[RESET]: (state, action, model) => {model.update(0)}
};
}
update(mergeObj)
: update the state by merging mergeObj. Returns undefined