This library generates actions creators, action types and reducers for you. It uses class as a syntactic sugar for generating actions and reducers.
Redux is great library which solves data management. However it introduces some boilerplate. In order to add one business logic, developer must create 3 different things (action type, action creator, reducer) and they do one thing together. That is why I have decide to create utility that allows declare them in one place. One business logic should be declared in one place.
This library is inspired by redux-actions and mobx
$ npm install --save redux-lightweight
or
$ yarn add redux-lightweight
Create class that has state
property as initial state and methods as actions.
import { createUpdater } from 'redux-lightweight';
export class Counter {
state = 10;
increment(amount = 1) {
return this.state + amount;
}
decrement(amount = 1) {
return this.state - amount;
}
}
export const [counterReducer, counterActions] = createUpdater(Counter);
counterReducer; // reducer for Counter class
counterActions; // action creator for Counter class - { increment, decrement }
redux-lightweight
exposes useUpdater
custom hook to make it easier working with reducers.
import React from 'react';
import { useUpdater } from 'redux-lightweight';
import { Counter } from './Counter';
function CounterView() {
const [counter, { increment, decrement }] = useUpdater(Counter);
return (
<div>
<p>{counter}</p>
<button onClick={() => increment()}>+</button>
<button onClick={() => decrement()}>-</button>
</div>
);
}
redux-lightweight
generates simple action creators and reducer. So you can work with them as usual.
import React from 'react';
import { connect } from 'react-redux';
import { counterActions } from './Counter';
function Counter({ counter, increment, decrement }) {
return (
<div>
<p>{counter}</p>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
const mapStateToProps = (state) => ({ counter: state });
const mapDispatchToProps = {
increment: counterActions.increment,
decrement: counterActions.decrement
};
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
In order to handle redux-lightweight
generated action creators in saga, you can access action type with action function itself:
import { takeEvery } from 'redux-saga/effects';
import { counterActions } from './Counter';
function* rootSaga() {
yield takeEvery(counterActions.increment.type, incrementWorkerSaga);
}
If you have already big reducers that are difficult to migrate then you can use library as action generator.
Arguments passed to actions will be array in payload
{
type: actionType,
payload: args // array of arguments
}
export class Counter {
increment(amount) {}
decrement(amount) {}
}
const [, counterActions] = createUpdater(Counter);
switch(type, payload) {
case counterActions.increment.type:
return state + payload[0];
case counterActions.decrement.type:
return state - payload[0];
default:
return state;
}
dispatch(counterActions.increment(1));
As redux-lightweight
works with classes, you can use extended classes as well. That is useful to reuse reducers and actions.
class Calculator extends Counter {
double() {
return this.state * 2;
}
}
export const [calculatorReducer, calculatorActions] = createUpdater(Calculator);
Now it generates 3 action creators:
increment
decrement
double
Basically redux-lightweight generates action creators, action types and reducers for you.
When you pass your class to redux-lightweight
, it generates following things for you:
- Action creator - Each method of class e.g increment, decrement
- Action type - Prefixed by class name e.g "Counter/increment"
- Reducer - Which handles all actions inside class
- In order to set initial state for reducer, declare
state
property on class.
- In order to set initial state for reducer, declare
class Counter {
state = 10; // Initial state for reducer = 10
increment(amount = 1) {
return this.state + amount;
}
decrement(amount = 1) {
return this.state - amount;
}
}
const [counterReducer, counterActions] = createUpdater(Counter)
counterActions
contains all methods ofCounter
class as actions. In this case there will be two actions:
counterActions.increment(100) // { type: "Counter/increment", args: [100] }
counterActions.decrement(100) // { type: "Counter/decrement", args: [100] }
counterReducer
is reducer that handles all actions of class. It is same as with followingswitch/case
statements:
switch(type) {
case "Counter/increment":
return state + amount;
case "Counter/decrement":
return state - amount;
default:
return state;
}
If you want to get action type for action then you can access it with type
property of action:
counterActions.increment.type // "Counter/increment"`
Creates reducer and action creators for given Updater class. Receives class that has state
property and methods.
const [reducer, actions] = createUpdater(Counter);
Custom hook for using Updater. Receives class that has state
property and methods.
function App() {
const [state, actions] = useUpdater(Counter);
}
This project is licensed under the MIT License - see the LICENSE file for details