Post/Code

HomeAboutUsesNow

Redux Notes.

Today I started learning some Redux. As I understand it, Redux, in short is a predictable state container for JavaScript apps with the primary goal being to improve the predictability of state in an application.

Instead of mixing application state in amongst UI code all over the app, Redux stores all data in once location. This data store is a state tree. Essentially one JavaScript object outside of the UI. The UI will then reference the state.

There are 4 elements in Redux:

  1. The state.
  2. Getting the state.
  3. Listening for changes to the state.
  4. Updating the state.

These functionalities are distributed amongst the following (simplified example):

  1. Store = state (+ the function of the store)
  2. Getting the state = getState function.
  3. Listening for changes to the state = subscribe function.
  4. Updating the state = dispatch function.

Actions.

Actions are events that trigger changes to state. They are javascript objects with a required type property and an optional payload.

Actions Creators.

Action creators are functions that create/return action objects.

Reducers.

Reducers are functions that take in state and actions and return new (not-mutated) state.

Store.

The store returns the store object. createStore must be passed a reducer with which to operate on the store. The store itself has three methods:

  • getState()
  • subscribe()
  • dispatch()

These methods have access to the state of the store via closure.

Here is a rudimentary example of a "Redux" store.

// library code
function createStore(reducer) {
  let state;
  let listeners = [];

  const getState = () => state;

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

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

  return {
    getState,
    subscribe,
    dispatch
  };
}

// app code: dev writes reducer function
function todos(state = [], action) {
  switch (action.type) {
    case "ADD_TODO":
      return state.concat([action.todo]); // is pure since concat returns a new array not a mutated array.
    case "REMOVE_TODO":
      return state.filter(todo => todo.id !== action.id);
    case "TOGGLE_TODO":
      return state.map(todo =>
        todo.id !== action.id ? todo : Object.assign({}, todo, { complete: !todo.complete })
      );
    default:
      return state;
  }
}

const store = createStore(todos);

store.subscribe(() => {
  console.log("Update state: ", store.getState());
});

store.dispatch({
  type: "ADD_TODO",
  todo: {
    id: 1,
    name: "Learn Redux",
    complete: false
  }
});

// const unsubscibe = store.subscribe(() => {
//   console.log("Update state again: ", store.getState());
// });

// unsubscribe();