Redux and React in ES6, Ch#06

Redux React Ch#06

  • ch#06: 54~61

Actions, Stores and Reducers

Actions

  • action creators
  • action type -> must
rateCourse(rating) {
  return { type: RATE_COURSE, rating: rating }
}

Store

  • single store
let store = createStore(reducer);

  • store.dispatch(action)
  • store.subscribe(listener)
  • store.getState()
  • replaceReducer(nextReducer)

What is Immutability

  • To change state, return a new object

What’s Mutable in JS?

  • immutable already! : Number, String, Boolean, Undefined, Null
  • Mutable: Objects, Arrays, Functions

example

state = {
  name: 'Cory House',
  role: 'author'
}

state.role = 'admin'; // here, traditional app, mutating state
return state
  • Immutable way of updating the state
state = {
  name: 'Cory House',
  role: 'admin'
}

Copy

  • Signature
Object.assign(target, ...sources)
  • Example
Object.assign({}, state, {role: 'admin'});
  • make sure {}
  • Object.assign is ES6 feature
  • must use babel-polyfill

Why Immutability

Clarity

  • Huh, who changed that state? -> The reducer, stupid!

Performance

  • if new object
  • if (preStoreState !== storeStore)
  • no need to go through each values of the states to compare

  • sorta like copy operator in c++ and comparing the object with pointer
  • Now it makes sense

Awesome Sauce

  • (Amazing debugging)
  • install Redux devtools extension in Chrome
  • Time-travel debugging
  • Undo/Redo
  • Turn off individual actions
  • Play interactions back

Handling Immutability

ES6

  • Object.assign => **
  • Spread operations

ES5

  • Lodash merge
  • Lodash extend
  • Object-assign

Libraries

  • react-addons-update
  • immutable.js

  • JS privmitives are immutable.

How do I enforce immutability?

  • trust
  • install redux-immutable-state-invariant
    • run it only in dev
  • immutable.js

Reducers

function myReducer(state, action) {
  // return new state based on action passed
}
  • reducer => meat grinder
  • (state, action) => state
function myReducer(state, action) {
  switch(action.type) {
    case 'INCREMENT_COUNTER':
      state.counter++;  // => mutating state , uh oh, can't do this
      return state;
    }
  }
}
  • working example
function myReducer(state, action) {
  switch(action.type) {
    case 'INCREMENT_COUNTER':
      return(Object.assign(
        {},
        state,
        {counter: state.counter + 1}
      );
  }
}
  • Reducers must be pure

Forbidden in Reducers

  • Mutate arguments
  • Perform side effects
  • Call non-pure functions: random

1 store, multiple reduers

All reducers are called on each dispatch

{ type: DELETE_COURSE, 1 }

Reducer = “slice” of state

  • loadingStatus
  • authors
  • courses

Redux FAQ

Write independent small reduer functions that are each responsible for updates to a specfic slice of state. We call this pattern ‘reducer composition’. A given action could be handled by all, some, or none of them

Summary

  • Actions
    • Represent user intent
    • must have a type
  • Store
    • dispatch, subscribe, getState…
  • Immutability
    • Just return a new copy
  • Reducers
    • must be pure
    • multiple per app
    • slice of state: meat grinder
COMMENTS