blog.jakoblind.no

Learn Redux by coding a Mini-Redux

There are lots of resources for learning Redux. There is the official documentation, examples, tutorials, blog posts, boilerplates, Youtube videos, podcasts, etc… The list goes on. Even though we have so many great resources to learn from, new developers coming in still sometimes gets confused. It’s an overwhelming amount of content and it can be difficult to filter out the relevant stuff.

A different learning strategy is to code a simple Redux yourself to develop a deeper understanding of the fundamental principles of the library. For me, it was a real breakthrough in my learning process when I did that. Now I feel i “get” Redux like I do with code I have written myself.

Don’t worry, this is not complicated. The core of Redux is surprisingly simple as you will see when reading and coding along to this blog post.

Before we start, we need an overview of what Redux does.

What does Redux do?

The whole point with Redux is to have one single source of truth for your application state. The state is stored as a plain Javascript object in one place: the Redux Store. The state object is read only. If you want to change the state, you need to emit an Action, which is a plain JavaScript object.

Your application can subscribe to get notified when the store has changed. When Redux is used with React, it is the React components that get notified when state changes, and can re-render based on new content in the store.

The store needs a way to know how to update the state in the store when it gets an Action. It uses a plain JavaScript function for this that Redux calls a reducer. The reducer function is passed in when the store is created.

Let’s get started coding!

To summarize, we need to be able to do three things with our store:

  1. Get the current state of the store

  2. Dispatch an action, which is passed as an argument to the reducer to update the state in the store.

  3. Listen to when the store changes

We also need to define the reducer and the initial state at startup time. Let’s start with this:

function createStore(reducer, initialState) {
  var currentReducer = reducer
  var currentState = initialState
}

1. Get state

Ok, so we have created a function that just saves the initial state and the reducer as local variables. Now let’s implement the possibility to get the state of the store.

function createStore(reducer, initialState) {
  var currentReducer = reducer
  var currentState = initialState

  return {
    getState() {
      return currentState
    },
  }
}

We can now get the state object with getState() ! That was easy.

2. Dispatch an action

Next step is to implement support for dispatching an action.

function createStore(reducer, initialState) {
  var currentReducer = reducer
  var currentState = initialState

  return {
    getState() {
      return currentState
    },
    dispatch(action) {
      currentState = currentReducer(currentState, action)
      return action
    },
  }
}

The dispatch  function passes the current state and the dispatched Action through the reducer that we defined at init. It then overwrites the old state with the new state.

3. Subscribe for changes

Now we can both get current state and update the state! The last step is to be able to listen to changes:

function createStore(reducer, initialState) {
  var currentReducer = reducer
  var currentState = initialState
  var listener = () => {}

  return {
    getState() {
      return currentState
    },
    dispatch(action) {
      currentState = currentReducer(currentState, action)
      listener() // Note that we added this line!
      return action
    },
    subscribe(newListener) {
      listener = newListener
    },
  }
}

Now we can call subscribe with a callback function as parameter that will be called whenever an action is dispatched.

We are done. Let’s use it!

That’s the whole mini-Redux implementation! It’s actually a stripped down version of the real Redux code.

On the official Redux Github page, there is an example on how to use Redux. We can copy/paste that example to test our own Redux implementation:

function counter(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1
    case "DECREMENT":
      return state - 1
    default:
      return state
  }
}

let store = createStore(counter)

store.subscribe(() => console.log(store.getState()))

store.dispatch({ type: "INCREMENT" })
store.dispatch({ type: "INCREMENT" })
store.dispatch({ type: "DECREMENT" })

Get the full code to run it on your machine by signing up to my email list below!

Conclusion

We have implemented a fully working Redux version in 18 lines of code. Pretty impressive!

This code we have written is obviously not production ready. Compared to the “real” Redux, we have removed error handling, don’t support multiple listeners, don’t support middlewares, etc.

Now that you know how the fundamentals of Redux works, you will be better equipped continuing your learning journey!

In the next blogpost, we will code the connect function which binds your Redux store to React components.

PS. Sign up to my email list below to get all the code from this blog post.


tags: