Redux for Beginners (Sort of)

Justin Tollison
Programmer’s Journey
6 min readMar 25, 2022

--

Well, this one will be a complicated post! Again, it’s been a few months and while I’d love to have posted earlier, I’ve been hard at work (and struggling) learning how to do Redux and learning how to develop a full-stack web application using React/Redux with Ruby on Rails. So, let’s jump right in into what Redux is and why it’s valuable to learn.

Photo by Lautaro Andreani on Unsplash

To begin in, what is Redux and why should I use it in my project? Let’s pull the definition directly from the website:

Redux is a pattern and library for managing and updating application state, using events called “actions”. It serves as a centralized store for state that needs to be used across your entire application, with rules ensuring that the state can only be updated in a predictable fashion.

Let’s break this down, Redux is a collection of prewritten code that will allow us to optimize our tasks in updating state, it also holds a store value that acts like a global state for the application. Basically, it allows us to have a global state for the entire project. Now, onto why that is important:

Redux helps you deal with shared state management… Redux is more useful when:

- You have large amounts of application state that are needed in many places in the app

- The app state is updated frequently over time

- The logic to update that state may be complex

- The app has a medium or large-sized codebase, and might be worked on by many people

So, imagine you have a massive project with a large hierarchy for your components. Your parent component passes down props to their children, and then they get passed down even further down the line and so forth. They all share the same State that is passed down from the top component in the hierarchy and they all use State or change it in some way. You can see where the potential for that to spaghetti is, if anywhere in the hierarchy where State is being passed down gets messed up in some way, it breaks the entire application.

Redux offers a solution, it lets us store the State and the necessary logic in our application in a JavaScript object separate from our hierarchy of components. Redux also encourages a single source of truth, being that State should be stored separately from our tree of components!

How does Redux work then and how do we implement it into our current project? Well, Redux unfortunately is quite complex, I myself have had a lot of trouble adding it and swapping over State from my components over into the Store (which is where State is stored in Redux) and changing the logic around of how my components grab and use state. I will give a quick explanation on how it works, but I recommend looking through the official Redux documentation at https://redux.js.org/tutorials/essentials/part-1-overview-concepts.

Here’s how to quickly install Redux into your application.

# NPM
npm install @reduxjs/toolkit
# Yarn
yarn add @reduxjs/toolkit

I prefer installing the Redux Core the toolkit, though both methods works. You will want to install the React bindings. You can also install developer tools, they aren’t required but can help if you know how to use them.

#Redux Core
# NPM
npm install redux
# Yarn
yarn add redux
#React bindings
npm install react-redux
#Developer Tools
npm install --save-dev @redux-devtools/core

In the image above, it actually gives a brief rundown of how it all works. State is stored globally in Store, a Javascript object, which is then passing in a reducer. It also has a getState method that returns the current value of state.

import { configureStore } from '@reduxjs/toolkit'const store = configureStore({ reducer: counterReducer })console.log(store.getState())
// {value: 0}

Reducer has a getState method that returns the current value of State. Reducer is a function that takes in the current State and an Action object and it decides how to update State through the actions and then returns State. Think of it as an event listener that handles State based on the actions it receives. There are some more rules to reducer, but we’ll move on.

const initialState = { value: 0 }function counterReducer(state = initialState, action) {
// Check to see if the reducer cares about this action
if (action.type === 'counter/increment') {
// If so, make a copy of `state`
return {
...state,
// and update the copy with the new value
value: state.value + 1
}
}
// otherwise return the existing state unchanged
return state
}

Continuing, you can also see that each component has a Dispatcher. The Store has a method called dispatch(), the only way to update the global State in store is to call store.dispatch() and to pass in an action object. The store will run the reducer function and save the new state value.

store.dispatch({ type: 'counter/increment' })console.log(store.getState())
// {value: 1}

Dispatching actions is similar to triggering events if we are to think of a reducer as the event listener. Our dispatcher triggers an action or event, the reducer takes in that action and then it updates state in store. Components will dispatch actions to our reducer that changes the value of State in store.

const increment = () => {
return {
type: 'counter/increment'
}
}
store.dispatch(increment())console.log(store.getState())
// {value: 2}

Another method to consider are the Selectors. Selectors are methods that know how to retrieve certain information from a Store’s state value. This can help to avoid repeating logic in different parts of the app that read the same State.

const selectCounterValue = state => state.valueconst currentValue = selectCounterValue(store.getState())
console.log(currentValue)
// 2

To summarize, we store our State’s value in a Redux Store, which is just a container of data separate from our component tree. The Store is created using the root Reducer. Store then calls the Reducer and saves the return value of the Reducer as its initial state, which is then passed to Store. When we want to update State, say through a button click action, we use Dispatch to dispatch an action to the Redux Store. The Store runs the Reducer function again, but with the previous state and the current action from Dispatch and saves the return value as the new state. Any UI element that has Selector (or is subscribed to state) will then re-render and update with the new State value. Essentially, the data flows such as this:

  • Create Redux Store using a Reducer
  • Reducer takes in initial State and an action to return State back to Store
  • Dispatch sends actions from components up to the Store
  • Store runs the Reducer function with the given actions from Dispatch
  • Reducer returns a new state value to Store after running the actions and stores it as the new global State.
  • All UI that is subscribed to the State in Store is updated and re-rendered using a Selector.

Whew! That was a lot of information in a short time, most of it was provided by the Redux documentation and from what I’ve learned from the Flatiron School curriculum! I know it’s all a bit frazzled, but I hope it does simplify up Redux and how it works somewhat. Redux is very complex and it’s understandable if you don’t get it at first, I still struggle with wrapping my head around it sometimes. Though, the benefits of Redux are immense and there are many more things it’s capable of doing than what I mentioned. Thanks for reading and keep on learning!

--

--

Justin Tollison
Programmer’s Journey

Unity Game Developer and Flatiron Software Engineering Alumni