Flux & Redux

I. Flux

  1. 4 parts of Flux architecture:

    • View
    • Actions
    • Dispatcher
    • Store
  2. Relationship

    • Store: model object managing all data; has updating methods as well
      • provide data to View
      • provide updating methods to Actions
    • Dispatcher: extends Event Emitter object
      • used by component to register event & callbacks
      • used by component to emit actions to call store updating methods
    • View: receive data from store
    • Actions: used by component to let dispather emit actions
    • Great article: http://www.ruanyifeng.com/blog/2016/01/flux.html

II. Redux

  1. store

    1. getState(): source of data
    2. dispath(): emit actions, execute reducer to update state
    3. subscribe(): component subscribe to receive updated state
  2. reducer

    • likeemitter.on, used to register all the updating functions for related actions
    • pure function
    • combineReducers(): used to make logic clean
  3. Store implementation

    1. How to use the store object

    2. 1
      2
      3
      4
      5
      6
      7
      import { createStore } from 'redux';
      let { subscribe, dispatch, getState } = createStore(reducer);
      // or
      let store = createStore(todoApp, window.STATE_FROM_SERVER)
      store.getState()
      store.dispatch()
      store.subscribe()
    3. redux provide an interface createStore() to create the store object

    4. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      const createStore = (reducer) => {
      let state;
      let listeners = [];

      const getState = () => state;

      const dispatch = (action) => {
      state = reducer(state, action);
      listeners.forEach(listener => listener());
      };

      const subscribe = (listener) => {
      listeners.push(listener);
      return () => {
      listeners = listeners.filter(l => l !== listener);
      }
      };

      dispatch({});

      return { getState, dispatch, subscribe };
      };
  4. An example using Redux

  5. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    const Counter = ({ value, onIncrement, onDecrement }) => (
    <div>
    <h1>{value}</h1>
    <button onClick={onIncrement}>+</button>
    <button onClick={onDecrement}>-</button>
    </div>
    );

    const reducer = (state = 0, action) => {
    switch (action.type) {
    case 'INCREMENT': return state + 1;
    case 'DECREMENT': return state - 1;
    default: return state;
    }
    };

    const store = createStore(reducer);

    const render = () => {
    ReactDOM.render(
    <Counter
    value={store.getState()}
    onIncrement={() => store.dispatch({type: 'INCREMENT'})}
    onDecrement={() => store.dispatch({type: 'DECREMENT'})}
    />,
    document.getElementById('root')
    );
    };

    render();
    store.subscribe(render);

III. React-Redux package

  1. connect():
    • connect UI component with it outer Controller component
    • usage: const Contrainer = connect(mapStateToprops, mapDispatchToProps)(UIComponent)
  2. mapStateToProps()
    • map state in Redux store to UI
    • like eventEmitter.subscribe(), will always get the updated state from Redux
  3. mapDispatchToProps

    • map actions dispatch() in Redux to UI
    • like eventEmitter.emit(), will trigger actions when UI event is fired, to execute reducer to update the state
  4. <Provider> component

    • an outer container, used to pass the state to inner components
    • using context attribute