npm install redux-class-decorators
yarn add redux-class-decorators
Writing reducers can be annoying, it takes time to create actionTypes, and actions, and to put it all into a switch. The benefits of this package is that you don't have to manage a separate actionTypes file. You get to define actions and a reducer in classes and all your types and API calls will live on just some objects. Just a matter of preference.
You haven't to declare or manage string constants. This package meets the standard for stream action objects and will automatically declare string constants for types. Also this package works well with redux-thunk.
If you have any questions, you can see examples of use.
Redux recommends creating constants, action creators and reducers separately. And we try to stick to this rule.
Reducer:
import { ReducerClass } from 'redux-class-decorators'
@ReducerClass('Profile')
class ProfileReducer {
static initialState = {
value: null,
loading: false,
}
static startLoading(state, action) {
return {
...state,
loading: true,
}
}
static finishLoading(state, action) {
return {
...state,
value: action.payload,
loading: false,
}
}
static clear(state) {
return {
...state,
value: null,
loading: false,
}
}
}
Actions:
import { ActionClass } from 'redux-class-decorators'
@ActionClass
class ProfileActionSet {
static get() {
return (dispatch, getState) => {
dispatch({
type: ProfileReducer.startLoading,
})
const profile = { id: 1, name: 'Mike' }
dispatch({
type: ProfileReducer.finishLoading,
payload: profile,
})
}
}
static clear() {
return {
type: ProfileActionSet.clear,
}
}
}
Usage:
// Create store
const store = createStore(ProfileReducer.$reducer, null, applyMiddleware(thunk))
// Get dispatch
const dispatch = store.dispatch
dispatch(ProfileActionSet.get())
// Actions:
// { type: 'PROFILE__START_LOADING' }
// { type: 'PROFILE__FINISH_LOADING', payload: { id: 1, name: 'Mike' } }
// state == { value: { id: 1, name: 'Mike' }, loading: false }
dispatch(Something.clear()) // { type: 'PROFILE__CLEAR' }
// state == { value: null, loading: false }
Example of using redux-class-decorators
:
PlumbingActionClass
allows you to use one class to work with different instances.
Reducer:
import { PlumbingReducerClass } from 'redux-class-decorators'
@PlumbingReducerClass('Banner')
class BannerReducer {
static $getInitialState() {
return {
value: null,
}
}
static setValue(state, action) {
return {
...state,
value: action.payload,
}
}
}
Actions:
import { PlumbingActionClass } from 'redux-class-decorators'
@PlumbingActionClass
class Banner {
static $getIndex(params) {
return params.type
}
static add(newValue) {
return {
type: BannerReducer.setValue,
payload: newValue,
}
}
}
Usage:
// Create store
const store = createStore(BannerReducer.$reducer, null, applyMiddleware(thunk))
// Get dispatch
const dispatch = store.dispatch
dispatch(Banner.add({ type: 'left', text: 'Test1' }))
// { type: 'BANNER__SET_VALUE', payload: 5 }
dispatch(Banner.add({ type: 'right', text: 'Test2' }))
// { type: 'BANNER__SET_VALUE', payload: 10 }
// state == { 'left': { value: 'Test1' }, 'right': { value: 'Test2' } }
MIT