Understanding the Power of Redux
By: Maxwell Harvey Croy
Tags: Software Engineering, Software Development, JavaScript, Web Development, React

Let’s take a more in-depth look into this State Management powerhouse.

As a relatively new React developer, one thing that’s stood out to me is how top-heavy my React apps can sometimes feel. While each component always has it’s own bells and whistles, the “lowest shared parent” can sometimes feel overloaded by the amount of stateful information it stores. Don’t get me wrong, lifting state is an essential concept in React and certainly one of the library’s most useful features, but I’ve always wondered if there’s a better way to do it.

Enter Redux.

What Is Redux?

Redux is a state management library created by Dan Abramov and Andrew Clark in 2015 that aims to provide you with a single source of truth for state across all components so you can easily access stateful information at any time.

Basing Redux somewhat on Flux, a pre-existing application architecture pattern used by the likes of Facebook, Dan developed the concepts that eventually led to the development of Redux while preparing for a presentation at React Europe.

Dan Abramov’s presentation on Hot Reloading at React Europe 2015, where the key concepts driving the development of Redux were first explored.

From this talk, Redux was born shortly thereafter, leading to a seachange in how state is handled in JavaScript web applications.

Redux was built so it could be used with any component-based JavaScript library, so if you’re working with Angular or Vue.js instead of React, Redux might still be the state management solution for you!

Why Should I Use Redux?

As I mentioned earlier, Redux can be incredibly useful for top-heavy applications that need to manage large amounts of dynamic or stateful information. By creating a central store of information, you can easily access any piece of information within that store across all components without getting confused about where that information should go and how it interacts with other parts of info.

This benefit also comes into play for applications with a large number of components. Sometimes, apps can get more complicated than we originally intended for them to be, and the lowest common parent can be several layers above where information is displayed or updated. By using Redux, we remove that complexity and make it easier to get information to where it needs to be.

If you’re building a smaller application with minimal amounts of stateful data, Redux might not be for you as it could be overkill. With that being said, adding Redux to a smaller project can hardly be considered bloat, as the tool is 2KB, so feel free to implement it at your discretion!

Getting Started With Redux

Installing Redux is relatively simple (you can use the docs for that), so let’s get into implementation. Redux is relatively simple — the library provides you with a central store that allows you to manage your application’s state from a single location through the use of three parts: the store, actions, and reducers.

Store

The store is the central location for your stateful data, and as such, there should only be one store in your application. Stores are easily implemented, as you can see if the example below:

const store = createStore(myStore);

From this store, we can read and update state and register and unregister listeners. While some of these processes are carried out through methods native to the store (such as subscribe, unsubscribe, and getState), most of the functionality you’ll build around your state will be handled by Actions and Reducers.

Actions

Actions are how we send information to our data store across components. Ultimately, Actions are just JSON objects that contain information on what action should be carried out and what information should be worked on as a result. A typical Action for login might look like (source):

{

type: "LOGIN",

payload: {

username: "foo",

password: "bar"

}

}

To use an action, we must first define it using an action creator. An action creator is simply a function that creates our action, which we will eventually send to a reducer for processing. An action creator might look like (source):

function postAdded(title, content) {

const id = nanoid()

return {

type: 'posts/postAdded',

payload: { id, title, content }

}

}

Once we’re created an action, it’s time for us to define our reducers so we can update state.

Reducers

Reducers are functions that take instructions from an action, update state based on those instructions, and return the new state. Reducers can take a bunch of different forms, but on example of what a reducer might look like is below (source):

const LoginComponent = (state = initialState, action) => {

switch (action.type) { // This reducer handles any action with type "LOGIN"

case "LOGIN":

return state.map(user => {

if (user.username !== action.username) {

return user;

} if (user.password == action.password) {

return {

...user,

login_status: "LOGGED IN"

}

}

});

In practice, Redux states are technically immutable, meaning they are never actually changed. Actions and Reducers work together to create copies of state when requested, create a new state to reflect the current state, and then set state to an entirely new value. Additionally, the data passed to a Reducer is never changed either, preventing any side effects that might impact your application.

Conclusion

Hopefully, this post has served as a useful starting point on your journey to learning more about Redux, an incredibly useful tool for managing state for complex applications.

Keep in mind, Redux isn’t the right solution for all projects out there, so if you want a bit more guidance on whether Redux is the right tool for you, Redux’s documentation contains helpful guidance.