October 24, 2017 Syed Shah

Introduction to Redux

Intended Audience

This post is intended for people with little to no understanding of Redux. I have excluded some details and have intentionally prioritized simplicity over completeness. My goal is to give the readers a jump start in Redux and present it as simply as possible by just focussing on the core concepts.

What is Redux?

Simply put, Redux is a set of tenets (3 in particular) on which you abide by. These tenets describe why, how and when your application state changes. They are:

1. Single state

Your entire application’s state is saved in a single state object. This is radically different from the best practices we were used to so far; i.e each component maintains and manages its own state.

2. State can only be changed by emitting ‘Actions’

The single state object mentioned above is read-only. The only possible way to change state is by emitting an action. Action is an object which describes an event. Note that emitting an action doesn’t itself changes the state. Action only specifies that some state changing event happened.

3. Actual state changes are made by ‘Reducers’

Reducers are the functions which actually modify the state. They are invoked in response to actions. An important property of a reducer is that it is a pure function i.e it returns the exact same output for the same inputs. In Redux a reducer takes an action and previous state as input and returns the new state.

Thats it! This is what redux is all about. If you were able to follow along, congrats! you now know redux. If not the following example will make it more clear to you!

Example: Photo Gallery App

In order to better our understanding of redux concepts lets take a hypothetical example of a photo gallery web app and map the aforementioned concepts on it.

So lets suppose we are asked to build a simple photo gallery web app which provides the following functionalities:

  1. Displays photos in a grid/list view
  2. Add picture
  3. Remove picture

1. Single state

We define the single state object tree as follows:

{
  pictures: [
    {pictureId:"1", url: "/pics/pic1.png"},
    {pictureId:"2", url: "/pics/pic2.png"},
    {pictureId:"3", url: "/pics/pic3.png"}
  ],
  viewType: "GRID"
}

2. Actions

The following actions could be emitted to initiate changes in state

AddPicture

{
  type: "ADD_PICTURE",
  picture: {url: "<picture_url>", id: "<picture_id">}
}

RemovePicture

{
  type: "REMOVE_PICTURE"
  id: "<picture_id>"
}

ChangeViewType

{
  type: "CHANGE_VIEW_TYPE",
  view:"<view_type>"
}

3. Reducers

Note: In the following reducer implementations, I am deliberately explaining implementation in comments rather than code. This is so that we could avoid over shadowing concepts with implementation details. In a follow up article we will cover the implementation part in depth.

addPicture

This reducer is applied to the ADD_PICTURE action

function addPicture(prevState, action) {
  if (action.type == "ADD_PICTURE") {
    // create a new state object (newState) from prevState
    // and concatenate action.picture to newState.pictures
    
    return newState;
  } else {
    return prevState;
  }
}

removePicture

function removePicture(prevState, action) {
  if (action.type == "REMOVE_PICTURE") {
    // create a new state object (newState) from prevState
    // and remove picture with action.pictureId to newState.pictures
    
    return newState;
  } else {
    return prevState;
  }
}

changeViewType

function changeViewType(prevState, action) {
  if (action.type == "CHANGE_VIEW_TYPE") {
    //create a new state object (newState) from prevState
    // set newState.viewType = action.viewType
    
    return newState;
  } else {
    return prevState;
  }
}

Putting it altogether

Now that we have defined the state, actions and reducers lets go over some examples of how we can emit actions to trigger state changes. But first lets assume we have the following two functions available:

  1. getState(): returns the application state (single state of the app)
  2. dispatch(state, action): emits an action and invoking all the reducers we defined above

Add a new picture

Add a new picture with picture id: 10

var action = {
  type: "ADD_PICTURE",
  picture: {url: "/pics/pic4.png", id: "10"}
}

dispatch(getState(), action)

Remove a picture

Remove the picture with id: 10

var action = {
  type: "REMOVE_PICTURE",
  id: "10"
}

dispatch(getState(), action)

Change view type to LIST view

Change the gallery view type to LIST view

var action = {
  type: "CHANGE_VIEW_TYPE",
  viewType: "LIST"
}

dispatch(getState(), action)

References

http://redux.js.org/

HTH 🙂

Share this...
Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn
Tagged: , , , ,

Contact Us

Get in touch to schedule your FREE consultation!