Learn the Basics of Redux by Writing Your Own Version in 30 Lines
Tags: react, redux, javascript, webdev
Published: 2020-09-22 13:03:55

---
title: Learn the Basics of Redux by Writing Your Own Version in 30 Lines
published: true
description: One of my favorite ways to learn how something works is to recreate it. Today, we're going to learn the basics of Redux by creating a simplistic version of it.
tags: react, redux, javascript, webdev
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/wgx1xoav310qrobjwyhl.png
canonical_url: https://typeofnan.dev/learn-basics-redux-by-writing-your-own-version-30-lines/
---

One of my favorite ways to learn how something works is to recreate it. In this post, we're going to learn the basics of Redux by creating a simplistic version of it.


<hr />

### If you enjoy this tutorial, please give it a 💓, 🦄, or 🔖 and consider:

📬 signing up for [my free weekly dev newsletter](https://buttondown.email/devtuts)
🎥 subscribing to [my free YouTube dev channel](https://www.youtube.com/c/devtutsco?sub_confirmation=1)

<hr />

# What Does Redux Accomplish?

Before we dive in, it's important to understand what Redux accomplishes. Redux is a _state management_ library. It helps you manage stateful information in an application. "Stateful information" is just a fancy way of saying information that needs to persist and be available during your application's use. This includes things like a user's name or whether the application is in "light" mode or "dark" mode.

State management libraries like Redux become especially useful when your application gets larger in size. Many people think Redux is a part of React or explicitly associated with React, but it's actually its own standalone library and can be used with or without React.

# The Basic Principles of Redux

The basic idea behind Redux is that you have a _centralized_ location for your stateful information and can _predictably_ update state. To accomplish this, Redux has the following basic structure:

- **A state object** - The state object contains the stateful information for your application. This could be information like the logged in user's name and whether they're in "light" or "dark" mode.
- **Actions** - Actions are objects that give Redux the information necessary to update state. By convention, an action object might have a `type` property and a `payload` property. If you wanted to set the user's name to "Frankie", your action might look like this: `{ action: "SET_USER_NAME", payload: "Frankie" }`
- **A reducer** - Reducers are functions. They take two arguments: 1) the current state, 2) an action object (as described above). The reducer uses the information provided in the action object along with the current version of the state and returns a new version of the state.
- **The store** - The store is an object that allows you to access the current version of the state and also allows you to _dispatch_ actions to update that state. The store object therefore has two properties, both of which are functions: `getState` and `dispatch`.

# Yikes, Am I Supposed to Understand All That?

One of Redux's biggest criticism is that it has a steep learning curve, so you definitely should not be concerned if you don't understand all of that. As we implement our own, stripped down version of Redux, these concepts should hopefully start clicking. And what _really_ helps is actually using Redux in the wild!

# Rolling Our Own Redux

Let's get started with rolling our own Redux! If you've used Redux bofore, you know that you generally create your `store` with a `createStore` function provided by the library. We're going to write this ourselves!

As I mentioned above, our store needs to allow us to access our `state` object by using a `getState` function. It also has to allow us to `dispatch` actions. Let's create a skeletal `createStore` function based on this knowledge.

```javascript
function createStore() {
  let state = {}; // Don't know what this is yet
  function getState() {
    return state;
  }

  function dispatch(action) {
    // Set state based on the action
  }

  return { getState, dispatch };
}
```

That's a pretty good start! Let's make some improvements. First off, we don't always want our initial `state` to be an empty object `{}`. Instead, we'll have `createStore` take an argument called `initialState`.

Next, our `dispatch` funciton has to do something with the `action` we passed it so that our state can be updated. The `reducer`, as described above, fits this need:

> Reducers are functions. They take two arguments: 1) the current state, 2) an action object (as described above). The reducer uses the information provided in the action object along with the current version of the state and returns a new version of the state.

So let's pass our current `state` object to the reducer along with the `action` and set our state variable equal to the return value.

Here are both of our enhancements implemented:

```javascript
function createStore(reducer, initialState) {
  let state = initialState;
  function getState() {
    return state;
  }

  function dispatch(action) {
    state = reducer(state, action);
  }

  return { getState, dispatch };
}
```

And that ends up actually being it for our simplified `createStore` function! More experienced Redux users might notice that we're omitting the third parameter from `createStore`. This parameter becomes important as you get into more advanced Redux, but for core principles we'll stick to this first two params!

Before we can use our `createStore` function, we'll need a `reducer`. Let's create a reducer that can either set a user name or set the display mode (light/dark).

As we've discussed, our `reducer` function takes the current `state` and an `action` as arguments and returns a new version of the state.

```javascript
function reducer(state, action) {
  switch (action.type) {
    case 'SET_USER_NAME':
      return {
        ...state,
        name: action.payload,
      };
    case 'SET_DISPLAY_MODE':
      return {
        ...state,
        displayMode: action.payload,
      };
    default:
      return state;
  }
}
```

Let's dissect what we've done here.

Our `reducer` takes a `state` argument and an `action` argument. We have a `switch` statement that will return different things based on the value of `action.type` (remember we discussed before that, by convention, our `action` object has a `type` and a `payload`).

If `action.type` is `"SET_USER_NAME"`, then we return a copy of our state but we overwrite the `name` key of state with the provided `action.payload`. Conversely, if `action.type` is `"SET_DISPLAY_MODE"`, we return a copy of our state but we overwrite the `displayMode` key. If the `action.type` isn't one of those two strings, we just return our state unmodified.

This is pretty much all we need, we can now take our home-rolled Redux for a test run!

# A Test Run

Here's a test run of our home-rolled Redux library. See inline comments for the play-by-play.

```javascript
// The createStore function we already wrote
function createStore(reducer, initialState) {
  let state = initialState;
  function getState() {
    return state;
  }

  function dispatch(action) {
    state = reducer(state, action);
  }

  return { getState, dispatch };
}

// The reducer we already wrote
function reducer(state, action) {
  switch (action.type) {
    case 'SET_USER_NAME':
      return {
        ...state,
        name: action.payload,
      };
    case 'SET_DISPLAY_MODE':
      return {
        ...state,
        displayMode: action.payload,
      };
    default:
      return state;
  }
}

// Create a new store! This will take our reducer
// and also an initial version of our state.
const initialState = { name: 'Guest', displayMode: 'light' };
const store = createStore(reducer, initialState);

// Change our user's name to "Frankie"
store.dispatch({
  type: 'SET_USER_NAME',
  payload: 'Frankie',
});

console.log(store.getState());
//{ name: "Frankie", displayMode: "light" }

// Change our display mode to "dark"
store.dispatch({
  type: 'SET_DISPLAY_MODE',
  payload: 'dark',
});

console.log(store.getState());
//{ name: "Frankie", displayMode: "dark" }
```

# That's Pretty Much It

Now we have this pretty nifty `store` object that accomplishes everything we wanted:

1. We have a centralized way to access our stateful information (by calling `store.getState()`)
2. We have a repeatable, predictable way to update our stateful information by dispatching actions (by calling `store.dispatch(action)`).

I hope you enjoyed this introduction to Redux!