Re-energize Your

with React and Redux

Jonathan Kemp


Jonathan Kemp

Senior Front End Engineer

@ Scripps Networks

Knoxville, TN

The Kemp Family

Follow Along:

Slides -

Repo -

Why React?

Why REact?

  • Build user interfaces
  • Reusable UI components
  • Data changes over time
  • Large applications

What Problems Does
React solve?


  • Modifying the DOM is expensive
  • Managing state changes in the DOM is complex


  • Performs updates as efficiently as possible
  • Manages UI updates for you


  • React makes use of a virtual DOM.
  • When data changes, React decides if an update is needed by building a new virtual DOM and comparing (diffing) them.
  • React only updates the parts that changed.

the React ecosystem:

What you should LEarn

In This Order:

  1. React itself
  2. npm
  3. JavaScript "bundlers"
  4. ES6
  5. Routing
  6. Flux

You don't need to learn all of these
to be productive with React.

Learning REact


You need to spend a lot of time setting up tooling to start to learn React.


  • No tooling is required.
  • Learn the tooling once you are comfortable with the basics.



Expressing display logic in template languages can be cumbersome


  • No templates
  • Markup and logic are tied together


create JavaScript objects
using HTML syntax

* Not Required


  • JSX provides the readability of HTML
  • "Designers" can contribute React code with JSX
// To generate a link in React using pure JavaScript:

React.createElement('a', {href: ''}, 'Hello!');

// With JSX this becomes:

<a href="">Hello!</a>


  • Dynamic data is represented as "props"
  • Passed as attributes in JSX syntax
  • Handles "state"

Best PRactices

  • Most components should be stateless
  • Parent components manage state
  • Children just render the data as props

Demo Time

Building Complex Applications

With React


  • The most popular way to share JavaScript
  • Most reusable components, libraries and tools in the React ecosystem are installed with npm
  • CommonJS modules (i.e. everything in npm) cannot be used natively in the browser

JavaScript Bundlers

JavaScript Bundlers

JavaScript “bundlers” “bundle” these modules into .js files that you can include in your web page with a <script> tag


  • Webpack
  • Browserify

Why Webpack?


  • Split your app into multiple files
  • Often replaces grunt or gulp
  • Supports AMD, CommonJS, among other module systems (Angular, ES6)
// webpack.config.js
module.exports = {
  entry: [
    path.resolve(__dirname, 'app/main.js')
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js'
  devtool: 'source-map',
  module: {
    loaders: [
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
      { test: /\.css$/, loader: 'style-loader!css-loader' }

Webpack Config

  "name": "recalculator",
  "version": "1.0.0",
  "description": "This is an example app built with React and Redux.",
  "main": "app/main.js",
  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build",
    "test": "echo \"Error: no test specified\" && exit 1"
  "repository": "jonkemp/recalculator",
  "author": "Jonathan Kemp <> (",
  "license": "BSD-2-Clause",
  "dependencies": {
    "bootstrap": "^3.3.6",
    "pubsub-js": "^1.5.3",
    "react": "^15.1.0",
    "react-dom": "^15.1.0",
    "react-redux": "^4.4.5",
    "redux": "^3.5.2"
  "devDependencies": {
    "babel-core": "^6.9.1",
    "babel-loader": "^6.2.0",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.5.0",
    "css-loader": "^0.23.1",
    "file-loader": "^0.9.0",
    "style-loader": "^0.13.1",
    "url-loader": "^0.5.7",
    "webpack": "^1.13.1",
    "webpack-dev-server": "^1.14.1"


major upgrade to the language

* Not Required

Learning ES6

  • If you just want to get things done with React, skip this
  • Not necessarily the preferred way (docs in ES5)
  • Not supported in browsers yet (your bundler can translate it for you)


Learning routing

  • Useful for Single-page Applications
  • Most popular router in the React ecosystem is 'react-router'
  • Don’t use a router if you aren’t building a SPA


Do I need Flux?

  • React is good at managing state.
  • Flux should only be added once many components have already been built.
  • If you aren’t sure if you need it, you don’t need it.

What problems does Flux solve?

  • Managing state in components is an anti pattern
  • Makes maintenance and adding new features easier
  • Makes data changes easy to reason about

the most popular 



* Not Required

Problems to Solve

As application complexity grows, managing state becomes harder.


At some point, you no longer understand what happens in your app as you have lost control over the when, why, and how of state changes.


  • A state container that will help your applications
    behave consistently
  • Avoids the complexity found in Flux
  • A functional programming approach (to Flux)

Redux Overview

  • State of your app is stored in an object tree inside a single store.
  • Only way to change the state tree is to emit an action, an object describing what happened.
  • To specify how the actions transform the state tree, you write pure reducers.
  • That’s it!
import { createStore } from 'redux';

 * This is a reducer, a pure function with (state, action) => state 
 * signature. It describes how an action transforms the state into 
 * the next state.
function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1
  case 'DECREMENT':
    return state - 1
    return state

// Create a Redux store holding the state of your app.
// Its API is { subscribe, dispatch, getState }.
let store = createStore(counter)

// You can use subscribe() to update the UI in response to state 
// changes.
store.subscribe(() =>

// The only way to mutate the internal state is to dispatch an action.
// The actions can be serialized, logged or stored and later replayed.
store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1

The Gist


  • Scales well to large and complex apps
  • Enables very powerful developer tools
  • Applications that behave consistently
  • Run in different environments (client, server, and native)
  • Easy to test

Differences from Flux

  • Redux doesn’t have a Dispatcher or support many stores.
  • Instead, there is just a single store with a single root reducing function.
  • Instead of adding stores, you split the root reducer into smaller reducers.

Get Started with Redux

  • Can be used with any view library, independent of React
  • Babel or module bundler not required
  • Install via npm

Three Principles of Redux

Single source of truth

The state of your whole application is stored in an object tree within a single store.


/* Prints
  visibilityFilter: 'SHOW_ALL',
  todos: [
      text: 'Consider using Redux',
      completed: true,
      text: 'Keep all state in a single tree',
      completed: false

Single source of truth

 A single state tree also makes it easier to debug or introspect an application.

State is read-only

The only way to mutate the state is to emit an action, an object describing what happened.

  type: 'COMPLETE_TODO',
  index: 1

  filter: 'SHOW_COMPLETED'

State is read-only

This ensures that neither the views nor the network callbacks will ever write directly to the state.

Changes are made with pure functions

To specify how the state tree is transformed by actions, you write pure reducers.

function visibilityFilter(state = 'SHOW_ALL', action) {
  switch (action.type) {
      return action.filter
      return state

function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [
          text: action.text,
          completed: false
    case 'COMPLETE_TODO':
      return, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: true
        return todo
      return state

import { combineReducers, createStore } from 'redux'
let reducer = combineReducers({ visibilityFilter, todos })
let store = createStore(reducer)


  • Pure functions
  • Take the previous state and an action,
    and return the next state
  • Return new state objects, instead of
    mutating the previous state



  • History tape
  • Every calculation gets saved to the history tape
  • Refer to calculations later or send them right back to the calculator
  • Allows you to see everything you have typed



  • Actions are payloads of information that send data from your application to your store.
  • Actions describe the fact that something happened.
  • They are the only source of information for the store.
  • Send them to the store using store.dispatch().

Action Types

  • Actions must have a type property that indicates the type of action being performed.
  • Types should typically be defined as string constants.

Action Creators

  • Functions that return an action
  • Pass the result to the dispatch() function
  • Can be asynchronous and have side-effects
 * action types

export const ADD_ENTRY = 'ADD_ENTRY';



 * action creators

export function addEntry(text) {
  return { type: ADD_ENTRY, text };

export function removeEntry(index) {
  return { type: REMOVE_ENTRY, index };

export function updateResult(result) {
  return { type: UPDATE_RESULT, result };



Reducers specify how the application’s state changes in response to actions.

Application State

  • Stored as a single object
  • Store data, as well as UI state
// Application State
                id: 1,
                expression: "5 * 3",
                result: 15
                id: 0,
                expression: "5 * 2",
                result: 10
    lastResult: 15

Reducers should:

  • Take the previous state and an action, and return the next state.
  • Given the same arguments, it should calculate the next state and return it.

Reducers should Not:

  • Mutate arguments
  • Perform side effects
    from '../actions/index';

function calculateApp(state, action) {
  switch (action.type) {

    case ADD_ENTRY:
      return Object.assign({}, state, {
        items: [
            id: state.items.reduce((maxId, todo) => 
                Math.max(, maxId), -1) + 1,
            expression: action.text,
            result: eval(action.text)

export default calculateApp;

    case REMOVE_ENTRY:
      return Object.assign({}, state, {
        items: [
          ...state.items.slice(0, action.index),
          ...state.items.slice(action.index + 1)

      return Object.assign({}, state, {
        lastResult: action.result

  • Copies the values of all enumerable own properties from one or more source objects to a target object
  • Returns the target object
Object Spread Syntax ...
  • Copy enumerable properties from one object to another in a more succinct way
  • Easy to return a new object

Splitting Reducers

  • Split the reducers into separate files
  • Independent, managing different data domains
  • Redux provides a utility called combineReducers()

import { combineReducers } from 'redux'

const calculateApp = combineReducers({

export default calculateApp

Redux Store

Redux Store

Holds the state and takes care of calling your reducer when you dispatch an action

The Store

  • Allows access to state via getState()
  • Allows state to be updated via dispatch(action)
  • Registers listeners via subscribe(listener)
import { createStore, applyMiddleware, compose } from 'redux';
import calculateApp from './reducers/index';

const localStore = store => next => action => {
  const result = next(action);
  localStorage.setItem('recalculator', JSON.stringify(store.getState()));
  return result;

const data = JSON.parse(localStorage.getItem('recalculator')) || 
    { items: [], lastResult: 0 },
  store = createStore(

Data Flow

Data Flow

  1. Dispatch an action
  2. Store calls the reducer
  3. Reducer returns the new state

React Redux

React Bindings for Redux

Presentational and Container Components

Container Components

  • Aware of Redux
  • Subscribe to Redux state
  • Dispatch Redux actions

Presentational Components

  • Not aware of Redux
  • Read data from props
  • Invoke callbacks from props


import React, { PropTypes } from 'react';
import Entry from './Entry';

const EntryList = ({ items, remove }) => (
  <div className="row">
    <ul className="list-group">
      {, index) => {
        return <Entry key={} {...item} remove={() => 
            remove(index)} />;

export default EntryList;
import React, { PropTypes } from 'react';
import PubSub from 'pubsub-js';

const Entry = React.createClass({
  render() {
    return (
      <li className="list-group-item">
        <button className="btn btn-warning btn-xs" type="button" 
            onClick={() => {
          PubSub.publish('entry', this.props.result);
        }}>Use Result</button>
        <button className="btn btn-warning btn-xs" type="button" 
            onClick={() => {
          PubSub.publish('entry', this.props.expression);
        }}>Use Expression</button>
        <button className="btn btn-danger btn-xs" type="button" 

export default Entry;
import React, { PropTypes } from 'react';
import PubSub from 'pubsub-js';

const EntryForm = React.createClass({
  componentWillMount() {
    this.pubsub_token = PubSub.subscribe('entry', (topic, value) => {
      this.input.value = value;

  componentWillUnmount() {

  handleChange() {
    let value;
    try {
      value = this.input.value !== '' ? eval(this.input.value) : 0;
    } catch (e) {
       // statements to handle any exceptions

  render() {
    return (
      <div className="row">
        <h1>{this.props.result} <button className="btn btn-success" type="button" 
            onClick={(e) => {
          this.input.value = this.props.result;
        }}><span className="glyphicon glyphicon-arrow-down" aria-hidden="true"></span>
        <form className="form-inline" onSubmit={(e) => {
          this.input.value = '';
          <div className="form-group">
            <input className="form-control" type="text" ref={node => {
              this.input = node
            }} onChange={this.handleChange} />
          <button className="btn btn-primary" type="submit">Submit</button>

export default EntryForm;


React Redux API

React Redux API

  • connect()
  • mapStateToProps()
  • mapDispatchToProps()

generating container components

With the React REdux API


Tells how to transform the current Redux store state into the props you want to pass to a presentational component.

import { connect } from 'react-redux';
import { addEntry, updateResult } from '../actions/index';
import EntryForm from '../components/EntryForm';

const mapStateToProps = (state) => {
  return {
    result: state.lastResult

const mapDispatchToProps = (dispatch) => {
  return {
    submit: (value) => {

    change: (value) => {

const AddEntry = connect(

export default AddEntry;

Receives the dispatch() method and returns callback props that you want to inject into the presentational component.

import { connect } from 'react-redux';
import { removeEntry } from '../actions';
import EntryList from '../components/EntryList';

const mapStateToProps = (state) => {
  return {
    items: state.items

const mapDispatchToProps = (dispatch) => {
  return {
    remove: (index) => {

const PushEntryList = connect(

export default PushEntryList;



Performs updates as efficiently as possible.
Manages UI updates for you.


Tooling is not required to get started.

Learn the tooling once you are comfortable with the basics.


Goal is to help your applications behave consistently and make state changes easier to reason about.

For more information:

React -

Redux -

react-webpack-template -

webpack-howto -


Slides -

Repo -

Thank YOU!

Re-energize Your Workflow with React and Redux

By Jonathan Kemp

Re-energize Your Workflow with React and Redux

  • 328
Loading comments...

More from Jonathan Kemp