Skip to content

Instantly share code, notes, and snippets.

@zcaceres
Created March 30, 2017 21:41
Show Gist options
  • Save zcaceres/bffad36e45cc3f9bfc6accb5204d0523 to your computer and use it in GitHub Desktop.
Save zcaceres/bffad36e45cc3f9bfc6accb5204d0523 to your computer and use it in GitHub Desktop.
FSA 1702, March 30, 2017

React - Redux

FSA 1702, March 30, 2017

Predictable State Container for Javascript Apps

We dispatch actions (an expression of intent). Redux changes our state for us in a store, and returns a new state. We don't change our state directly. Then we can REWIND TIME.


So what the hell does that mean?

State: condition of the app (data) at a particular moment in time

Props: data passed down from a container to a component

State changes, props are just data that is passed around. Although props do change, they do not change as far as the component is concerned. It just receives the props from above.

Global vs. Local State

Some dynamic information is generated by and only needed by that component.

Other information is needed by the application as a whole.

For a countdown: the remaining time is a local state (only the countdown needs to know this). When the countdown reaches zero, only then do we need to let the rest of the app know (global state).

For an input element: local state changes to hold and display value. When we submit we are sending value to global state for processing.

How State is Affected?

In the context of a game, there is a set of finite possible actions that changes state.

What is Redux?

Separate from React. It is a way of organizing state. It does not depend on React.

Solving the problem of: opaque and nondeterministic applications, where many elements are linked together causing re-renders, server requests etc in long, confusing chains.

  • a small tool or containing, accessing and affecting a state of information (often called a 'state')
  • often part of React architecture (though not a necessary part)
  • gateway drug to strictly functional programming

NOT:

  • not a React-specific tool
  • not react-redux (that's just an npm module)
  • not so useful for small applications
  • not the only way of managing your state

LIVE CODE

// for an app.js file
import React from 'react';
import ReactDOM from 'react-dom';
import {createStore} from 'redux';

const initialState = {x: 0, y: 0}

/* Similar to vanilla JS reducer function
a Redux reducer function does 'action' on state.
Each time an action is performed the action is performed on the state created
by the last action */
const store = createStore( (state=initialState, action) => {

  // We always return a new state each time we're in this function

  const newState = { x: state.x, y: state.y } // creates a copy of the state, so we never mutate our state

  // Switch statements are common in Redux reducer functions
  switch (action.type) {
    case 'MOVE_UP':
      newState.y = state.y + 1;
      break;
    case 'MOVE_DOWN':
      newState.y = state.y - 1;
      break;
    default:
      return state;
  }

  return newState; // return new changed state or a copy of the original state
} );

// DISPATCH an ACTION to this STORE
store.dispatch({ type: 'MOVE_UP' });
/* State will only change if we pass a valid action to the store.
Dispatch gives the reducer an action */

setTimeout(() => store.dispatch({type: 'MOVE_UP'}, 1000));
setTimeout(() => store.dispatch({type: 'MOVE_UP'}, 2000));
setTimeout(() => store.dispatch({type: 'MOVE_UP'}, 3000));
setTimeout(() => store.dispatch({type: 'MOVE_UP'}, 4000));
setTimeout(() => store.dispatch({type: 'MOVE_UP'}, 5000));

//SUBSCRIBE to a STORE, showing what changes have occurred
store.subscribe( () => {
  ReactDOM.render(
    <div>
    <h1>{ store.getState().x }</h1>
    <h1>{ store.getState().y }</h1>
    </div>
    , document.getElementById('app')
  )
  console.log(store.getState());
})


console.log(store.getState());

Mutation and Asynchronicity

In the past, these two things made our lives difficult. Mixing mutation and async is dangerous... like coke and Mentos. We might get race conditions and other problems.

What are the 3 principles of Redux?

  • Single source of truth. Redux holds a single source for our state. In React we store state all over our app, this is what we change in Redux.
  • State is READ-ONLY. Redux changes state if it is allowed -- there is no 'writing' or mutating of the state. You express an intent and Redux makes a new state if its allowed and gives you back a new state.
  • Changes to state are made with pure functions (no side-effects). We want our UI layer to be pure functions.

Neither React nor Redux does deep checking for changes – it creates a new state which tells the rest of your app to react to it.

Mechanics of Redux

Store

  • The singular holder of information
  • Receive dispatched signals (actions) meant to affect state
  • Provides an interface to access and listen to state

Reduce

  • the part of the store that decides based on signal (action) what the new state is
  • creates new states per action rather than mutating previous states
  • can be replaced or chunked (broken up into smaller functions)

Action

Time Traveling with Redux Dev Tools

Download React & Redux Dev Tools, do it!

  • Add Redux dev tools as middleware
  • React tab in Chrome dev tools

We can rewind time and see the state of our app at different moments. We can also skip certain actions to see what would have happened if we did not do them and 'replayed' the history.

Immutability and Purity

We need a new version of the state rather than mutating the state.

  • we don't want unintended side effects or information out of synch

  • think of it like a git commit

Staying Immutable

  • Merge objects with Object.assign() -- with a new copy of an empty objects
  • concat your arrays, rather than pushing, because it returns an array
  • [..listOfItems, new item], uses ES6 spread to

Purity:

  • referential transparency
  • same function with same arguments should always produce the smae output
  • no side-effects!

Common Impurities

  • AJAX calls in our store
  • Any randomization or use of dynamic closure information (outside the store)

YOUR REDUCER SHOULD BE A PURE FUNCTION

Other Stuff

  • combine reducers into a single composite reducer
  • Middleware: useful between your dispatch and your reducer. Useful for logging

History: Flux

Redux is a real library that implements Flux (a conceptual idea for managing state in applications).

'Redux' -> Reducers + Flux

                ------- Action ------
                |                    |
Action --> Dispatcher --> Store --> View

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment