https://habrahabr.ru/post/327244/Наверняка многие из вас, кто постоянно работают с React + Redux (а может не только с React), постоянно совершают множество однотипных действий. В оригинальном исполнении задача эта монотонная и включает в себя постоянное создание экшенов и редюсеров. Тем более, если приходится работать с какими-то экстраординарными кейсами, в игру включаются экшены с префиксами.
Ваш покорный слуга также испытал очень много
батхерта страданий, пока работал по старинке, через switch → case, но я взглянул на задачу немного с другой стороны и привёл к единообразию это в более удобную функционально — объектную форму записи.
И так — после некоторого времени я (
master-7) и мой коллега (
one-more) попробовали справиться с этим страшным сном фронтэндера и создали весьма интересную библиотечку
Redux-Utils.
Конечно же, мы попытались написать общепонятное и исчерпывающее ридми, но для затравки — несколько примеров в статье.
Одна из самых интересных фичей — это объектное создание редюсеров.
import {Reducer} from 'redux-util'
import {UserState} from 'types/UserState'
import {
GET_USER_DATA_REQUEST,
GET_USER_DATA_SUCCESS,
GET_USER_DATA_FAIL
} from 'services/actionTypes'
const initialState: UserState = [];
export default Reducer(initialState, {
[GET_USER_DATA_REQUEST]: () => null,
[GET_USER_DATA_SUCCESS]: (state, action) => ({
...state,
data: action.users
}),
[GET_USER_DATA_FAIL]: (state, action) => ({
...state,
error: action.error
})
});
Как вы можете видеть, код стал намного более читабельным по сравнению с записью вида:
import {Reducer} from 'redux-util'
import {UserState} from 'types/UserState'
import {
GET_USER_DATA_REQUEST,
GET_USER_DATA_SUCCESS,
GET_USER_DATA_FAIL
} from 'services/actionTypes'
const initialState: UserState = [];
export default function Reducer(state = initialState, action) => {
switch (action.type) {
case GET_USER_DATA_REQUEST:
return null;
case GET_USER_DATA_REQUEST:
return {
...state,
data: action.users
};
case GET_USER_DATA_FAIL:
return {
...state,
error: action.error
};
default:
return state;
}
Ну и киллер фича номер два — посмотрим на создание экшенов:
import {buildGenericActionCreator} from 'redux-util'
const START_LOADING = 'START_LOADING';
const END_LOADING = 'END_LOADING';
export const startLoadingActionCreator = buildGenericActionCreator(START_LOADING);
export const endLoadingActionCreator = buildGenericActionCreator(END_LOADING);
// ....
import {startLoadingActionCreator, endLoadingActionCreator} from 'loading-reducer'
const PREFIX = 'PREFIX';
const startLoading = startLoadingActionCreator(PREFIX);
const endLoading = endLoadingActionCreator(PREFIX);
export const loadUser = () => (dispatch: Dispatch) => {
dispatch(startLoading());
return api.fetchUser().then(
response => {
dispatch(
loadUserDataAction(response)
);
dispatch(endLoading());
}
);
};
И еще много интересного вы можете найти в ридми проекта! Надеюсь, данная библиотека сделает вашу работу легче.