Should I Use Redux?

Rebecca Rosenberg
The Startup
Published in
5 min readSep 15, 2020

Starting a new application means drawing out a blueprint of what you want it to look like, and thinking about how you are going to implement whatever you are going to do before you even write any code. As a JavaScript developer, I often find myself questioning whether or not I’ll need to use Redux.

Redux is a state management technology created by the React team. It cleans up your application’s state massively by creating a global “store” where all state and state changes can be held, regardless of which file or page you’re in. Redux also helps developers steer clear of prop drilling, as parent components no longer need to directly pass downstate to their children, grandchildren, great-grandchildren, etc. via props. Let’s take a look at what this means through a create-user instance.

First, we’ll need a sign-up form in order for our user to create an account.

// src/Components/SignupForm.js //import {createUser} from '../Actions/userActions.js'
import React from 'react'
import {connect} from 'react-redux'
class SignupForm extends React.Component{

state = {
username: '',
password: '',
}
handleChange = e => {
this.setState({
[e.target.name]: e.target.value
})
}
handleSubmit = e => {
e.preventDefault()
this.props.createUser(this.state)
}
render(){
return(
<form onSubmit={this.handleSubmit}>
<input type="text" name="username"
placeholder="Username"
value={this.state.username}
onChange={this.handleChange}/>
<input type="password" name="password"
placeholder="Enter Password"
value={this.state.password}
onChange={this.handleChange}/>
<input type="submit" value="Signup"/>}
</form>
)
}
}
export default connect(null, createUser)(SignupForm)

Let’s go through this and see where Redux has been inserted into our React form.

import {createUser} from '../Actions/userActions.js'

This createUser business is an action that we’ve created in a file called userActions.js, and we’re importing it into our SignupForm.js file. Since we imported it, we now have access to this method. Next up:

import {connect} from 'react-redux'

Let’s start from ‘react-redux’. As the documentation says:

React Redux is the official React binding for Redux. It lets your React components read data from a Redux store, and dispatch actions to the store to update data.

Let’s break that second sentence down a bit. The first part of it is saying that by importing tools from the React Redux library, such as Connect, we give our React components access to everything in the Redux store. That means global state and actions as well. In order to bind the Redux store to your React components, you must:

export default connect(null, createUser)(SignupForm)

The first argument in Connect is null. That’s because we aren’t giving this component any state from the global store. We’ll go through an example of giving a React component state from the global store later. For now, we must leave it as null, since connect is expecting there to at least be a function which will give state to this component’s properties. If we just had our createUser action in there without null, it would be very, very confused.

Actions are the bread and butter here. They give our application the information that our reducer will need to modify state. We are calling our createUser action in our React component in this line of code:

this.props.createUser(this.state)

This is sending the state (AKA, the user object we just created through this form), to our userActions file. Before we move on: in order to give your React component access to an action, you must:

  1. Import the action from its respective file
  2. Import Connect from React Redux
  3. Export & Connect your function or class as written above

Our infamous createUser action will look like this:

// src/Actions/userActions.js //export const createUser = (userObj) => {
return (dispatch) => {
fetch('http://localhost:3000/users', {
method: 'POST',
headers: {
'accepts': 'application/json',
'content-type': 'application/json'
},
body: JSON.stringify(userObj)
})
.then(response => response.json())
.then(data => {
dispatch({type: 'CREATE_USER', payload: data})
})
}
}

Yep, nothing special… for the most part. It looks like a normal fetch call, except what’s this dispatch business?

Redux allows us to deal with asynchronous fetching by giving us a middleware tool: Thunk. In order to deal with these asynchronous fetchings, we must give our actions dispatches internally. In essence, Thunk gives us access to dispatch, which gives us access to asynchronosity in our app. If we were to be authenticating our user, we would also have a dispatch pointing to a type of ‘SHOW_ERROR’ with a payload of whatever the error message is in the case that there was an error with the POST request. For now, life is good and we don’t have to worry about authentication, and we only need one dispatch:

dispatch({type: 'CREATE_USER', payload: data})

This calls on our user reducer, which is going to modify our app’s global state.

// src/Reducers/userReducer.js //defaultState = {currentUser: {}}export function userReducer(state = defaultState, action){
switch (action.type) {
case 'CREATE_USER':
return {
...state, state.currentUser: action.payload
}
default:
return state;
}
}

Here, our application sees that our action’s type is ‘CREATE_USER’, so it passes the data (our newly created user from our fetch call, stored in payload) to the userReducer’s ‘CREATE_USER’ case, where our state is modified to be equal to the user who just created an account. We can now tell any of our React components about this new user by mapping state to props. Let’s give it to Profile for now:

// src/Profile.js //import React from 'react'
import {connect} from 'react-redux'
class Profile extends React.Component{
render(){
return(
<h1>{this.props.currentUser.username}</h1>
)
}
}
const mapStateToProps = state => {
return {currentUser: state.currentUser}
}
export default connect(mapStateToProps)(Profile)

Our Profile now has access to our currentUser and is able to print to the screen in an h1 tag the currentUser’s username. You’ll notice our friend Connect has yet again been imported from React Redux. Now, instead of giving us access to a specific action, it’s giving us currentUser from our global Redux store. Where the first argument in our prior example for Connect was null, now it’s the function mapStateToProps, which is giving our React component, Profile, the prop of currentUser.

So, should I use Redux? If you’re going to be using a piece of information in multiple components, yes. It’ll clean up your code and make it easier for you to access information anywhere. However, beware of your asynchronous actions and make sure you know what’s going on in your application at all times.

That being said, if an application of my own had one parent that needed to pass down props to just one generation, I probably would stick to using React state. And, of course, you can always use both forms of state in the same application, given the right circumstances.

--

--