redux-way
v0.2.5
Published
A small, simple and immutable model to manage data in your Redux store.
Downloads
32
Maintainers
Readme
redux-way
A small, simple and immutable model to manage data in your Redux store.
Motivation
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
Installation
npm install --save redux-way
Usage
Declare your model
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)}
};
}
Register your model and create store
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));
Connect your composant
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)
Use redux-saga
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)}
};
}
Api
Model
update(mergeObj)
: update the state by merging mergeObj. Returns undefined