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
// ./app/reducers/index.js

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  // WebApp only
})

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 ) {

    // example of Initiating
    case DAYPASS_BROWSER_SHOW_DETAIL:
      return {
        ...initialState,
        ...param
      }

    // example of Accumulation
    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

results matching ""

    No results matching ""