0.0.8 • Published 2 years ago
easy-ts-redux v0.0.8
Easy-TS-Redux
Write Redux in TS with minimum or zero boilerplate
- Redux Ducks compliant
- Immer - built in support
- Redux Saga - scalable async handling with generators
Installation
npm i easy-ts-redux
or
yarn add easy-ts-redux
Usage
Two major part: easyStore()
and easyReducer()
Create Slices with easyReducer()
Parameters:
initialState
(required) - must be some kind of objectprefix
(required) - its for avoiding action name collision (came from ReduxDucks)
import { easyReducer } from "easy-ts-redux";
const { reducer, action, actionWithPayload, wartchers } = easyReducer(
{ foo: "bar", isEasy: true },
"easy"
);
export default reducer;
It's genetic so you can restrict the state type
import { easyReducer } from "easy-ts-redux";
interface State {
foo: string;
isEasy: boolean;
}
const { reducer, action, actionWithPayload, wartchers } = easyReducer<State>(
{ foo: "bar", isEasy: true },
"easy"
);
export default reducer;
reducer
is the Slice itself (it should be the default export)action()
andactionWithPayload()
for create your actionswatchers()
return all saga watcher function (parameter ofeasyStore()
)
Create actions with action()
and actionWithPayload()
Both function has the same parameters, except actionWithPayload
exept the type of the payload
type
(required) - unique identifier for the actionsaga
(optional) - generator function for async data or dispatching other actions. (if provided this function get payload from action call)reducerFn
(optional) - actual reducer function what modify the state
Important
Either
saga
orreducerFn
must provided (or both), otherwide the action throw an errorsaga
always has one arg whitch is the type propreducerFn
use immer internally, this means you can freely mutate the state.
import {easyReducer} from 'easy-ts-redux';
import {put} from 'redux-saga/effects'
const {reducer, action, actionWithPayload, wartchers} = easyReducer({foo: 'bar'}, 'easy');
export const toggleEasy = action({
type: 'TOGGLE_EASY',
reducerFn: (state) => {
state.isEasy = !state.isEasy;
}
})
export const srtFoo = actionWithPayload<string>({
type: 'SET_FOO',
saga: function*(__reducerFnType, payload) { // __reducerFnType always provided, payload from action call
//yield some async call
const newPayload = payload + 'easy'
yield put({type: __reducerFnType, payload: newPayload}) //call the reducerFn
}
reducerFn: (state, payload) => {
state.foo = payload;
}
})
const fooWatchers = watchers; // Unfortunatly you can'r export watchers out of the box
export fooWatchers;
export default reducer;
Drawback! The reducerFn
's payload always be any
inside actionWithPayload()
Create store with easyStore()
Parameters:
reducer
(required) - object of Sliceswatchers
(optional) - Array of generatedwatchers
middlewares
(optional) - Array of middlewares
import {easyStore} from 'easy-ts-redux';
import foo. {fooWatchers} from "./foo"; // Since you export the reducer as default, you can use any name
//optionally create Store type
export type Store = {
foo: ReturnType<typeof foo>
}
const store = easyStore({foo}, [fooWatchers])
This method do the followings:
- generate and run
sagaMiddleware
- parse all
watchers
and combine them into a single array, what is consumed by sagaMiddleware - configure @redux-devtools/extension for development mode
- create actual store