How redux works?

Redux is a predictable state container for javascript applications. In layman's term, We store our data in a centralized place and pass it where ever needed by the application.

Few points about redux:

  1. Single source of truth - A plain single object to store your application data.
  2. Predictable - Behaves consistently no matter the environments (client, server and native).
  3. Developer Friendly - With redux devTools it is easy to debug and test our application.
  4. Flexible - Works with any UI layered application.

Below are the core concept of redux:

Skeleton code:
function createStore() {
  // To get the state
  function getState() {}

  // To dispatch or send an action
  function dispatch() {}

  // To subscribe to the state change
  function subscribe() {}

  // Return the above methods
  return { getState, dispatch, subscribe };
}

// To combine all the reducers
function combineReducers() {}

Step 1: createStore

To create our data store of the application. The main concept of redux is we can have only one store. createStore() method accepts three arguments as following.

  1. Reducer (Root reducer)
  2. Preloaded state (initial state - optional)
  3. Enhancer (optional) - Just to reduce the scope of this post we will not look into this.

createStore function will return 3 methods such as getState, dispatch, subscribe.

Step 2: getState

This method returns always updated state from the store.

function createStore(reducer, preloadedState, enhancers) {
  // If preloaded state else empty object
  let state = preloadedState || {};

  // Return the store state
  function getState() {
    return state;
  }

  return {
    getState,
  };
}

Step 3: subscribe

This method is useful when we want to listen to whenever the store state is updated. subscribe() also returns unsubscribe() method so that we can opt-out when we no longer need it.

function createStore(reducer, preloadedState = {}, enhancers) {
  // If preloaded state else empty object
  let state = preloadedState || {};

  // To store the list of subscribers for the state change
  let listeners = [];

  // Return the store state
  function getState() {
    return state;
  }

  // To subscribe to state change
  function subscribe(listener) {
    listeners.push(listener);

    // Returns an anonymous function to unsubscribe
    return function () {
      listeners = listeners.filter((l) => l != listener);
    };
  }

  return { getState, subscribe };
}

Step 4: dispatch

Dispatches an action that contains information about the change. The information is plan object which contains type and payload if required. This is the only way to update the state in the redux store.

Dispatch method does 2 things:

  1. Update the state using the type in the reducer passed to createStore() when we created the store.
  2. Calls all the subscribers if present after the state has updated.
function createStore(reducer, preloadedState = {}, enhancers) {
  // If preloaded state else empty object
  let state = preloadedState || {};

  // To store the list of subscribers for the state change
  let listeners = [];

  // Return the store state
  function getState() {
    return state;
  }

  // To subscribe to state change
  function subscribe(listener) {
    listeners.push(listener);

    // Returns an anonymous function to unsubscribe
    return function () {
      listeners = listeners.filter((l) => l !== listener);
    };
  }

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

    listeners.forEach((listener) => listener());
  }

  // To initializing the store with initial state of the reducers
  dispatch({ type: '@@redux/INIT' });

  return { getState, subscribe, dispatch };
}

Step 5: combinerReducers

Combine reducers function is to combine all reducers and call it to update the state when an action is dispatched.

combinerReducers function does the following:

function combineReducers(reducers) {
  return (state = {}, action) => {
    return Object.keys(reducers).reduce((nextState, key) => {
      nextState[key] = reducers[key](state[key], action); // Calling the reducers
      return nextState;
    }, {});
  };
}

Final thoughts

I have learned so much about redux by writing this post and I hope you have learned something new as well. The code I wrote is just to show how redux would have been implemented. And this code is only for learning purposes. Not meant to be used in production or development.

Thanks for reading to the end. If you have any doubts post your comments below. See ya in the next post.

Join 305+ Readers

Sent out once every month. No spam 🤞