I recently (re)watched Dan Abramov’s Egghead.io series on Learning Redux. In it, he walks the viewer through creating their own Redux Store from scratch.

I decided to repeat the exercise on my Sandbox.io account, with the addition of some tests to back things up. The result is so simple, the entire source can be inlined below:

function createStore(reducer) {
  let state;
  let listeners = [];

  const getState = () => state;

  const dispatch = action => {
    state = reducer(state, action);
    listeners.forEach(listener => listener());
  };

  const subscribe = listener => {
    listeners.push(listener);

    return () => {
      listeners = listeners.filter(l => l !== listener);
    };
  };

  // Set the initial state
  dispatch({});

  return {
    getState,
    dispatch,
    subscribe
  };
}

Granted it is a super-simplified version of the actual Store that’s shipped with Redux, but it serves as a nice learning tool to remind you just how simple Redux is at its core.

Code walkthrough

Here’s a brief overview of what’s happening in the code.

Firstly we accept a reducer function as the only argument to createStore.

function createStore(reducer) {}

This function will be called during store.dispatch() and should accept the current state and the current action being dispatched and return the “next” state object.

For illustration purposes here’s an example reducer I’m using in my tests:

const reducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case "UPDATE_NAME":
      state = {
        name: action.name
      };
      break;

    default:
      break;
  }
  return state;
};

Next, back in our createStore method, we initialise two private vars to track internal data:

  1. state – tracks the store’s current state.
  2. listeners – an array containing the store’s current subscribers.

Following this we can implement the store.getState() method which simply returns the current value of the state variable we just initialised above.

const getState = () => state;

With this in place, we can create the store.dispatch() method, which accepts an action object and calls the reducer to retrieve the “next” version of the state, updating the internal state as it does so.

It also notifies all the current “subscribers” of the change to the state.

const dispatch = action => {
    state = reducer(state, action);
    listeners.forEach(listener => listener());
};

For illustration purposes, here’s how we might call dispatch with an action object:

store.dispatch({
    type: "UPDATE_NAME",
    name: "David"
});

Finally we implement the store.subscribe() method, which accepts a function and adds it to the list of current subscribers to be notified when the state updates.

const subscribe = listener => {
    listeners.push(listener);

    return () => {
        listeners = listeners.filter(l => l !== listener);
    };
};

Notice that it also returns a function, which when called will unsubscribe the current listener via the closure.

Want to learn more?

And that’s it! Super simple, but you could use it just like the Redux store as shown in the tests I wrote.

If you’d like to learn about Redux or just to refresh your memory of how things work, I highly recommend Dan’s course. Nothing better than being taught about Redux by the person who created it.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.