Reducers
- A reducer is an function that convert the raw data to minimal data in state machine
- Say, given an user object, if we are just interested on its ID, all attributes other than ID should be dropped in state management
- Reducer is not unique for redux,
- the reducer in mapReduce in data science is exactly describing the same things.
- the
_.reduce
in lodash is exactly sharing the same behaviour
- Should always return a new reference to overwrite the current sub-state.
- Should learn the use of immutable.js
Design principle: Simplicity
- Always store the minimal data for state machine
- Catalog should be mounted to structural storage like realm, couchdb
- model-based reducer consists of state-of fetching, version and identity
- flow-based / scene-based reducer consists of state-of input and procedure
Authorized:
email: String // identity
data_of_birth: Timestamp
authorization_bearer: String // JWT, as state-of-version
// age: Number // should be a selector to calculate using moment
// is_logined: Boolean // should be a selector to check if authorization_bearer is available and active
ProgrammeCatalog:
is_fetching: Boolean // for loading indicator
iat: Timestamp // Issue At, as state-of-version
// items: Collection // Should be in structured database
AccountLogin:
email: String
msisdn: String
stay_logined: Boolean
awaiting_verification: Boolean
LocationSearch:
keyword: String
import { combineReducers } from 'redux'
import Authorized from '../../common/reducers/Authorized';
import ProgrammeCatalog from '../../common/reducers/ProgrammeCatalog';
import AccountLogin from '../../common/reducers/AccountLogin';
import LocationSearch from '../../common/reducers/LocationSearch';
import recaptcha from './recaptcha';
const rootReducer = combineReducers({
Authorized,
ProgrammeCatalog,
AccountLogin,
LocationSearch,
recaptcha
})
export default rootReducer
Design principle: Either clone from initial or previous
- Reducer are usually triggered due to two types of actions
- Initiating: showItemDetail, startUserLoginFlow, resetShoppingCart
- always in this format
{ ...initialState, ...param }
- Accumulation: updateAccountEmail, refreshVodList, toggleBookmark, changeProfilePicture
- always in this format
{ ...state, ...param }
import _ from 'lodash';
import {
DAYPASS_BROWSER_SHOW_DETAIL,
DAYPASS_BROWSER_UPDATE_QUANTITY }
from '../constants';
const initialState = {
selected_country_code: null,
quantity: 1,
daypass_id: null,
};
export default function DaypassBrowser (state = initialState, action) {
const { type, ...param } = action;
switch ( type ) {
case DAYPASS_BROWSER_SHOW_DETAIL:
return {
...initialState,
...param
}
case DAYPASS_BROWSER_UPDATE_QUANTITY:
return {
...state,
...param
}
default:
return state;
}
}
Design principle: Manage in micro way
- Reducer could be sophisticated
import {
CART_UPDATE,
SHIPPING_INFO_UPDATE,
CARD_DETAIL_UPDATE,
CONTACT_UPDATE }
from '../constants';
const initialState = {
cart: {
id: null,
items: [],
coupon: null,
},
shipping: {
district: null,
address_line_1: null,
address_line_2: null,
name: null,
contact_number: null,
},
payment_method: {
type: 'cash',
card: null,
},
contact: {
title: null,
name: null,
number: null
}
}
const cart = (state = initialState.cart, action) => {
const { type, ...param } = action;
switch (type){
case CART_UPDATE:
return {
...state,
...param
}
}
}
const shipping = (state = initialState.shipping, action) => {..}
const payment_method = (state = initialState.shipping, action) => {..}
const contact = (state = initialState.contact, action) => {..}
const CartCheckout = combineReducers({
cart,
shipping,
payment_method,
contact
})
export default CartCheckout