HomePortfolioBlogs

Redux in a nutshell

Understanding the basics of redux

Redux is a library used to manage your applications state.

Before redux, sending data to a parent component from a child component in React was stressful. Since React encourages a one-way data flow, we had to use callbacks to do this.

Redux solves this problem and A LOT more.

In the interest of being extra simplistic, think of a React application that sends the whole applications data down in the form of props, allowing every component to be purely functional and not class components with state. (Here’s a great article by Lail Brown about functional components and class components).

Every component would then be written out having access to props only, allowing you to use class components only when you absolutely need to modify state based on the components behavior.

Redux allows us to do just this — Have one global state and send appropriate pieces of it down into child components that can access the data via props.

This allows for us to easily manage state and maintain a global view of our application, instead of trying to piece together individual components state.

I got bored of making simple counter applications, so I added a new angle to things this time. Here’s a link to the repo on github.

An emotive counter app that changes its feelings based on the count.

Emotive Counter

The building blocks: Redux essentially has 3 main parts.

  1. The Store
  2. Reducers
  3. Actions

The Store:

The store is the part of redux that’s responsible for holding the complete state of our application. Think of all of the data of your application stored as a single object, rather than multiple tiny ones.

If you’ve worked with MongoDB before, you already had to do this before deciding the structure of your database (or the state of your application), and I think it’s amazing that Redux encourages this as well.

Another way to think of the store is the global state.

import { createStore } from ‘redux’; // import createStore from redux
import counter from ‘./reducers’; // import the reducer (more about this below)
export default createStore(counter);

Reducers:

Reducers are pure functions that are responsible for changing the store. The cool thing about them though, is that instead of actually 'modifying' the store, they copy the old one and return a new 'modified' one. This makes the global store immutable, instead of getting lost in a mess of unintended modifications on hidden a list of our state changes.

If Redux wasn’t built this way, imagine how complicated our state would get if we accidentally appended data that we meant to over write, or vice versa.

Another cool thing about reducers is that since they’re pure functions, they’re easy to unit test.

Reducers take in two arguments: the previous state, and an action.

import Emotions from ‘../data/Emotions’;

const initialState = {
  count: 0,
  emotions: Emotions
};

function counter(state = initialState, action){
  const count = state.count;
  switch(action.type){
    case ‘touch’:
      return { count: count + 1, emotions: Emotions };

    case ‘reset’:
      return {count: 0, emotions: Emotions }
    default:
      return state;
  }
}

export default counter;

Actions:

Actions are the second argument that reducers accept, and they’re used to decide how the store needs to be changed.

They are essentially objects that, at the minimum, have to have a 'type' property. This allows the reducer to perform state modifications based on the action’s type. Additional properties can be passed in if they need to be used in the reducer also. To modify the state, actions are dispatched which allows them to be received by the reducer, which in turn modifies the state.

export const touch = function touch() {
  return { type: "touch" }
}
export const reset = function () {
  return { type: "reset" }
}

Presentational and Container Components:

When developing an application using React and Redux, certain ideas arose that made the blend of these much simpler.

The main idea was the introduction of container components and presentational components.

Knowing these are important because they allow us to have a separation of concerns for the state management and the JSX (or mark-up) we write.

Presentational components:

The presentational components are components that have no trace of redux in them. They’re purely built for display purposes, and pull the state and behaviour of that particular component from the props.

These components are functional components and it’s easy for developers, who haven’t learned redux yet, to dive into them and understand what’s going on.

import React from "react"
import Buttons from "./Buttons"
import Numbers from "./Numbers"
const Display = (props) => {
  return (
    <div id="display">
      <Buttons touch={props.interact} count={props.value} reset={props.reset} />
      <Numbers count={props.value} emotions={props.feelings} />
    </div>
  )
}
export default Display

Container components:

The container components are what we use to tie the presentational components to redux. They define the component’s individual state, and decide what peices of the global store are relevant to that particular component.

These components are wrapped around their presentational components to allow them to have the props that are relevant only to them.

// 'connect' from react-redux connects the container component to the presentational one
import { connect } from "react-redux"
import Display from "../components/Display"
import { touch, reset } from "../actionCreators/index"
function mapStateToProps(state) {
  return {
    value: state.count,
    feelings: state.emotions,
  }
}
function mapDispatchToProps(dispatch) {
  return {
    interact: () => dispatch(touch()),
    reset: () => dispatch(reset()),
  }
}
const CounterContainer = connect(mapStateToProps, mapDispatchToProps)(Display)
export default CounterContainer

Imagine the alternative of having every component having access to the whole store. This would be giving components access to much more than behavior than they’d need. Dan Abramov (the author of redux) wrote a great article about presentational and container components.

Conclusion

And that’s Redux in a nutshell! There’s so much more to Redux, like understanding how to make asynchronous requests, using middleware, action creators and so on.

The redux documentation is written brilliantly and I highly encourage you go through it and build a small application (like I first did) when starting out with redux.


Thanks for reading through! 🚀

If you're interested in seeing more of my blogs, please sign up below:

Sign Up For More Blogs

But first... are you a human?

Yes

No

© 2022, Ashcodes