DEV Community

KevinZ-CS
KevinZ-CS

Posted on

Redux Explained

In this blog we will be discussing what exactly is redux and how it works under the hood when using a redux library. So what is redux? Redux is a library that is used to help manage an application's global state. It allows state to be managed in a way that's more predicable and scales well to larger applications. So what exactly does this all mean? Well in order to understand this definition we must first understand the three core principles when it comes to redux which is as follows:

  • Single Source of Truth
  • State is Read Only
  • Changes are made with pure functions

Single Source of True and Data Flow

So to elaborate on the first principle, redux focuses on a single source of truth. This single source of truth is referred to as a store where the state of an application lives. Normally when using a framework like react, state is shared between components by passing them as props. But with redux every component can access the state via store without the need to pass props. This greatly simplifies the architecture of the application and results in neater and more predicable code.

State is Read Only

When we say state is read only we mean that the only way to change the state is to emit an action. The keyword to remember here is action. An action is an object that describes what happened. In other words, actions describe how a state should be updated. From a code standpoint actions are used with a dispatch function which is made available to the application via store. When the dispatch function is called it signals that the user wants to update a state and in order to know the instructions on how to update the state, an action is passed in as an argument. Within the dispatch function the reducer function is then called with the action as an argument. (more on reducers in the next section)

Changes are made with pure functions

As mentioned in the previous section, in redux there is a function called a reducer. A reducer is a pure function in the sense that it is a function that only returns a value and has no side effects. So what exactly does this reducer function do? Well the reducer function takes in 2 arguments, the current state and an action, and returns an updated state.

Putting it all together

Now that we've gone over how redux works conceptually lets see an example. We are going to manually create functions that replicates the functionality of the redux library to illustrate what is going on under the hood.

function createStore(reducer) {
   let state;

   function getState() {
       return state
   }

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


   dispatch({ type: "@@init" })

   return { getState, dispatch }
}

Enter fullscreen mode Exit fullscreen mode

In the above code we are replicating a store by creating a store function. As mentioned previously, a store is where state lives and also provides access to the dispatch function. This is shown within the store function where we initiate a state variable and provide a getState function that simply returns that variable. Then we have a dispatch function that takes in an action as an argument which is then passed into the reducer along with the current state. The reducer function returns an updated value that is then assigned to the state variable.

Finally, the createStore function will return an object that contains the getState and dispatch functions which can be access through dot notation like any other object. A brief side note, the dispatch function is also called within the store with the init action as you might have noticed. This is added so that when the store is initially accessed, render within dispatch will be called and assigned an initial value to the initiated but undefined state variable. (This will be clearer once we look at an example of a reducer function).

Now lets look at the reducer function within dispatch. Here is an example of what a reducer function might look like.

const initialState = {
   count: 0,
   running: true
}


function reducer(state = initialState, action) {
   switch (action.type) {
       case "increment":
           return {
               ...state,
               count: state.count + 1
           }
       case "decrement":
           return {
               ...state,
               count: state.count - 1
           }
       default:
           return state
   }
}

Enter fullscreen mode Exit fullscreen mode

Besides having the job of taking in a state and action, the reducer is also responsible for setting an initial value for the state. In this case we define an initialState variable and set that as the default value for the state argument which ties in with the previous example and explains why we initiated the state variable in the store but left it undefined.

Next we have the switch statement where a case will run depending on the action type. For example, lets say we call the dispatch function and pass in an action with the type "increment". In our reducer, we will hit the "increment" case and update our state based on that case and return the updated state. At the end of our switch statement we also have a default value where we simply just return the state if the action matches none of our cases.

Conclusion

As stated before the above code simply just gives an idea of what occurs under the hood. The redux library provides alternative ways to access these functionalities without needing to manually write out some of the above code such as the getState or dispatch function. Once the redux library is imported and your application is set up accordingly all the redux related functions will become available and can be accessed using specific keywords. Redux is an incredibility useful library and we only just covered the foundation! Hope this helps with your redux journey!

Top comments (0)