Redux!

Predictable state container for JavaScript apps

Structure of this talk

  • Basic concepts
  • API overview
  • Some advanced stuff you can do
  • Recap and useful learning model

Why Redux?

Single state atom

{
  "todos": [
    {
      "text": "Listen to this talk",
      "completed": true
    },
    {
      "text": "Read the docs",
      "completed": false
    },
    {
      "text": "Try Redux",
      "completed": false
    }
  ],
  "visibilityFilter": "SHOW_ALL"
}

Actions

{
  "type": "ADD_TODO",
  "text": "Try Redux"
}

Reducers

(oldState, action) => newState

Functions are pure and nothing is destroyed

State 1

State 2

State 3

Action A

Action B

The view is derived

from the state

State

View

Actions

Redux API

The store

import {createStore} from 'redux'
import reducer from './reducer'

const store = createStore(reducer)

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

store.dispatch({type: "MY_ACTION"})

Action creators

  • Pure helper functions that return an action
export const addTodo = (text) => {
  return {
    type: 'ADD_TODO',
    text
  }
}

Reducers

const initialState = {foo: "bar", bar: "baz"}

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'SET_FOO':
      return {
        ...state,
        foo: action.foo
      }
    default:
      return state
  }
}

Multiple reducers

import {combineReducers} from 'redux'
import todos from './todos'
import visibilityFilter from './visibilityFilter'

export default combineReducers({
  todos,
  visibilityFilter
})

Usage with React

import {connect} from 'react-redux'
import TodoList from '../components/TodoList'

export default connect(
  mapStateToProps, // aka selector
  mapDispatchToProps // or action creators hash
)(TodoList)

Selectors

appState => componentProps

Advanced selectors

  • memoizee (two e's)
  • reselect
  • (but not Ramda memoize)

Async actions

  • REQUEST
  • RESPONSE
  • ERROR

Middleware

Intercept dispatched actions

Thunk middleware

export function asyncActionCreator() {
  return (dispatch, getState) => {
    // ...
  }
}

Async example

export function asyncActionCreator() {
  return dispatch => {
    dispatch({type: "REQUEST"})
    fetch("/my-resource")
      .then(processResponse)
      .then(results => 
        dispatch({type: "RESPONSE", results}))
      .catch(error =>
        dispatch({type: "ERROR", error}))
  }
}

More stuff

you can do

Redux logger middleware

Redux devtools

const store = createStore(todoApp, window.devToolsExtension && window.devToolsExtension())

React devtools

Save state to localStorage

Analytics middleware

Server-side rendering

Performance

  • shouldComponentUpdate()
  • Wrap a stateless components
  • Potential upcoming PureComponent
  • connect() only re-renders on change

Exceptions to state being in one place

  • Minor UI state
  • Google "Thinking in React"
  • redux-form for repeated patterns
  • URL state (maybe...)

Things I'm interested in learning about next

  • MobX
  • Observables/RxJS
  • Elm

Dreyfus model

of skill acquisition

5. Expert

4. Proficient

3. Competent

2. Advanced beginner

1. Novice

Google it for a free chapter from "Pragmatic Thinking and Learning"

1. Novice

  • Great docs and tutorials
  • Clear recipe to follow
  • Very popular/good community
  • "Safe choice"

2. Advanced beginner

  • Each concept understandable in isolation
  • Can actually get stuff done
  • Again, good docs

3. Competent

  • Can "take initiative" and plan out a complex app
  • Unlikely to regret choosing Redux
  • "Don't use a boilerplate"

4. Proficient

  • One framework among many
  • Key maxims/concepts
    • Single state atom
    • Everything is pure functions
  • Notice things that other people think are important

5. Expert

???

The end

Redux!

By David Moody