Redux is a state management tool which helps us manage data for our applications. It exists in a strange space between the front and back end of an application which often confuses beginners about its role in an application. To clarify, let's look at an example example use case.
A back end developer has implemented a REST API which opens up the applications database for use on the front end. An example of the REST API may be the WordPress API, Netlify or Mongo DB. The front end developer will then use Redux to pull this data into the front end of the application. The front end developer will likely utilise a user interface library such as React which they connect to Redux to create an automatically updating User Interface.
Considering redux is just plain JavaScript, it is possible that the backend developer could use Redux to store data in the database but there are much better methods for the back end of the application so I would advise you just think of Redux as a front end library.
It's also worth noting that Redux isn't always necessary, whereby if an application has a simple data structure, the React state management, such as the Context API, or just passing it down through props, is often enough.
Having provided some context to where Redux sits in the web development let's look at it in more detail.
Redux is a surprisingly small library, and at it’s most basic it can be written in 97 lines of code. Take a look at this code written by Dan Abramov, the creator of Redux – Redux Simplified. As you can see there isn’t too much off it. Of course you aren’t expected to be able to understand it from looking at that, but you should take confidence that the concepts, when boiled down are relatively simple.
Before reading this article, I would advise that you should have a good understanding of JavaScript and also of functional programming. If you don’t understand functional programming, I would recommend reading my two part series on it – Functional Programming Part 1. Redux is based on the concepts of functional programming and it will help you follow along.
Put simply, Redux is a JavaScript library, which manages the state (aka data) of our application. It is a library that has evolved over years of research into how best to manage large, complicated state. It allows us to add, edit and remove state in a logical, scalable and secure way. Within this library there are a few key concepts we should understand.
- Store
- State
- Action Creators
- Reducers
Before explaining each of them, read the below metaphor which I use to understand what is happening. As you work through the list, it will help build an image in your mind of what is going on.
Imagine you have a large amount of money and want to deposit it in your bank. You have a briefcase which has £100,000 in cash and a slip of paper in it that says, “Deposit this money”. You go into the bank and give the teller at the desk the briefcase. The teller opens the briefcase, read’s slip of paper and picks up the cash. They then walk to the bank vault and store your money inside. The bank teller returns to update you that your money had been stored. Having completed what you need you leave the bank!
Now we have that image in mind, let's walk through each of the above and see if you can make a connection between it and each of the concepts.
Store
The place where we ‘store’ all of our applications data (aka state). It provides as a ‘single source of truth’ of our applications data. It is stored in a single JavaScript object. Pretty simple right? It’s worth noting that this would then be stored in a database, e.g.
State
State is our applications data. It’s all the information we include in our application, e.g. users, emails, names, books, book titles, authors etc. Also pretty simple!
Action creators
Things start to become ever so slightly more nuanced here. When learning about redux you will often learn about just ‘actions’ and not ‘action creators’. In my opinion, this abstraction doesn’t reflect the internals of Redux and ends up confusing beginners. As such, I have jumped straight to explaining ‘action creators’. An ‘action creator’ function returns an object (the action). The action has two properties, the type (aka name of the action aka ADD_TODO) and the data (aka the new state aka ‘Go to the shops’). If needed, we pass our new state, into our action creator function, often referred to as the payload. Let’s introduce our first bit of code as I feel it will help clarify things. In this instance, the type is ADD_TODO and the payload will be the todo text. You will then notice to call our action we dispatch it too the store. Our store listens out for these dispatches and forwards them to our reducer. Our reducer is what will handle the logic of our application.
// Our action creator. We can see it is returning an object which has two values, the type and the data.
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
// Dispatch is a redux function.
dispatch(addTodo('Buy some eggs'))
// It's worth noting that you can pass an action directly into dispatch e.g. the below but the above pattern is more applicable in real world applications.
Reducers
Reducers specify how the applications state changes in response to our action we have sent. Every time an action is dispatched, it runs through our reducer function which tests the type of action, and then and then runs the relevant code. Redux requires reducers should be pure functions. This was covered in my functional programming series mentioned above but essentially means they should not edit the existing state, they instead should return a new state with the new changes. This is commonly achieved using the JavaScript spread operator. This rule of enforcing immutability is part of what makes Redux so useful, in that it provides tools such as easy undo / redo, time travelling to find old versions of your applications and more.
Take a look at the below reducer. Note the switch statement which allow us to add multiple tests for different types of actions, e.g. we could also add an UPDATE_TODO underneath other ADD_TODO reducer.
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
{
text: action.text
}
]
default:
return state
}
}
To use our reducer, we would then have to pass it into our store, which we can do using the following code. This will mean that anytime a ‘dispatch’ event is made, our store will run it through our reducers, thus updating our state!
const store = createStore(todos)
A visual guide for redux revisited
Let’s revisit our initial bank metaphor we used to understand Redux. If you hadn’t already guessed which was which, please take a look at the below.
-
Ourselves / user input
- We need to deposit our cash into a bank so we put it in a briefcase, with instructions what to do and our cash. In a Redux application, the user input might be a button click to ‘deposit money’.
-
Briefcase / action creator
- The briefcase contained a paper slip which is our action type, and our the cash which is our payload. We then dispatched our briefcase to our bank teller.
-
Bank teller / reducer.
- The person that took the briefcase and decided what to do with it aka put it in the bank vault.
-
Bank vault / store
- The place where we store everything.
Let’s try and reinforce this metaphor with an actual image. Notice that the action creator goes into the store first. That’s because it’s our store that is listening which then passes it into the router. This link isn’t displayed perfectly by the bank metaphor, but it’s not a big leap in your imagination to understand it.
Conclusion
As you can see, the general concepts of Redux aren’t overly complicated, but there are a few small nuances that may trip you up the first time around. As such, it helps to have a good visual image of Redux. For more on the topic, including how Redux connects with React please follow me on social media using the links below!
Make sure to follow me on twitter or dev.to for more tutorials to help with your journey into software engineering.
Top comments (0)