Редукторы — это чистая функция в Redux. Чистые функции предсказуемы. Редукторы — единственный способ изменить состояния в Redux. Это единственное место, где вы можете написать логику и вычисления. Функция Reducer примет предыдущее состояние приложения и отправляемого действия, вычислит следующее состояние и вернет новый объект.
Следующие несколько вещей никогда не должны выполняться внутри редуктора:
- Мутация аргументов функций
- API-вызовы и логика маршрутизации
- Вызов не чистой функции, например, Math.random ()
Ниже приведен синтаксис редуктора —
(state,action) => newState
Давайте продолжим пример показа списка товаров на веб-странице, который обсуждается в модуле создателей действий. Давайте посмотрим ниже, как написать его редуктор.
const initialState = { isLoading: false, items: [] }; const reducer = (state = initialState, action) => { switch (action.type) { case 'ITEMS_REQUEST': return Object.assign({}, state, { isLoading: action.payload.isLoading }) case ‘ITEMS_REQUEST_SUCCESS': return Object.assign({}, state, { items: state.items.concat(action.items), isLoading: action.isLoading }) default: return state; } } export default reducer;
Во-первых, если вы не установили состояние в «initialState», Redux вызывает reducer с неопределенным состоянием. В этом примере кода функция JavaScript concat () используется в ‘ITEMS_REQUEST_SUCCESS’, которая не меняет существующий массив; вместо этого возвращает новый массив.
Таким образом, вы можете избежать мутации состояния. Никогда не пишите напрямую государству. В ‘ITEMS_REQUEST’ мы должны установить значение состояния из полученного действия.
Уже обсуждалось, что мы можем записать нашу логику в редуктор и разделить ее на основе логических данных. Давайте посмотрим, как мы можем разделить редукторы и объединить их вместе в качестве корневого редуктора при работе с большим приложением.
Предположим, мы хотим создать веб-страницу, где пользователь может получить доступ к статусу заказа продукта и просмотреть информацию в списке пожеланий. Мы можем разделить логику в разных файлах редукторов и заставить их работать независимо. Предположим, что действие GET_ORDER_STATUS отправлено для получения статуса заказа, соответствующего некоторому идентификатору заказа и идентификатору пользователя.
/reducer/orderStatusReducer.js import { GET_ORDER_STATUS } from ‘../constants/appConstant’; export default function (state = {} , action) { switch(action.type) { case GET_ORDER_STATUS: return { ...state, orderStatusData: action.payload.orderStatus }; default: return state; } }
Аналогично, предположим, что действие GET_WISHLIST_ITEMS отправляется, чтобы получить информацию о списке пожеланий пользователя, соответствующую пользователю.
/reducer/getWishlistDataReducer.js import { GET_WISHLIST_ITEMS } from ‘../constants/appConstant’; export default function (state = {}, action) { switch(action.type) { case GET_WISHLIST_ITEMS: return { ...state, wishlistData: action.payload.wishlistData }; default: return state; } }
Теперь мы можем объединить оба редуктора с помощью утилиты Redux combReducers. CombReducers генерирует функцию, которая возвращает объект, значения которого являются различными функциями редуктора. Вы можете импортировать все редукторы в файл редуктора индекса и объединить их вместе как объект с соответствующими именами.
/reducer/index.js import { combineReducers } from ‘redux’; import OrderStatusReducer from ‘./orderStatusReducer’; import GetWishlistDataReducer from ‘./getWishlistDataReducer’; const rootReducer = combineReducers ({ orderStatusReducer: OrderStatusReducer, getWishlistDataReducer: GetWishlistDataReducer }); export default rootReducer;
Теперь вы можете передать этот rootReducer методу createStore следующим образом: