Learning Redux: A step beyond “todos” and “async” examples


For the past two days I’ve been into Redux. It’s a framework-agnostic JavaScript library for easier handling of all application’s state. Specialty of Redux is that application state is stored in one object (and not different object for different data domain) and that functions reducers which manipulates part of the state never mutate it but return rather new state.

Redux has really good documentation and couple of official examples with various difficulty and that’s where I started. I’ve read two introductory chapter and chapter about basics, studied the three simplest example applications (vanilla counter, counter and todos) trying to memorize how different parts fit together. Then I went on studying async example in the next chapter, which is basically only about how to do server calls and then updating application state. I’ve also studied shoping-cart which is slightly richer example. I’d like to stress that things didn’t clicked right away but after couple of rereads and a sleep they started to click, I just had to be patient.

For exercise I decided to apply idea of async example to todos example. It went really well. Here is a recap of what was added to load posts from server when user opens the web application (I’ve skipped informing state about beginning of posts fetching since it was nothing new):

actions/index.js

import fetch from 'isomorphic-fetch'

// existing code left out for brevity

export const receivedTodos = posts => {
  return {
    type: 'TODOS_RECEIVED',
    posts
  }
}

export const fetchTodos = () => {
  return dispatch => {
    fetch('http://localhost:3000/todos')
      .then(data => data.todos)
      .then((todos) => dispatch(receivedTodos(todos)))
  };
}

reducers/todos.js

const todos = (state = [], action) => {
  // ...
    case 'TODOS_RECEIVED':
      return action.posts
    default:
      return state
  }
}

main.js

import 'babel-polyfill'
import 'es6-promise' // added
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import createLogger from 'redux-logger'

import todoApp from './reducers'
import App from './components/App'
import { fetchTodos } from './actions'

let store = createStore(
  todoApp,
  {},
  applyMiddleware(thunkMiddleware, createLogger())
)

store.dispatch(fetchTodos());

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)