0.2.5 • Published 6 years ago

redux-way v0.2.5

Weekly downloads
7
License
MIT
Repository
github
Last release
6 years ago

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