Photo by Artem Sapegin on Unsplash

Getting Started with React/Redux, Boiler Plate Syntax for Functional Components

Hyrum Butler
7 min readFeb 14, 2021

--

If you have heard of React then chances are you have also heard of Redux. The two were made for each other like peas in a pod. Literally, Redux was made for React applications.

If you have done any work with React then chances are good that you have debugged your code and have run into some issues passing state through props at some point.

And even if you have worked on a few apps with React and Redux chances are that setting up Redux for your React app can turn into a boiler plate scavenger hunt of sorts.

So this post aims to provide that boiler plate with just the right amount of fluff to not feel like you’re copy pasta-ing. We will be covering the imports, exports, and basic setup of our new React/Redux application.

Because the focus of this post is not to show the variety of ways to use Redux, rather how to set it up, we will use the classic counter example. A button to decrement our state of the counter and a button to increment the state of our counter.

First, if you are looking for more fluff then here is a video series by Dan Abramov (coauthor of Redux) explaining Redux himself. The series is a bit dated but the concepts and structures hold true.

Additionally, if you are looking for a similar guide with a little more hand holding, here is a fantastic post going through a similar setup.

Also, below is a great guide to how the parts of our React/Redux application will pass information along.

Getting Started Setting Up Our Files

Start with npx create-react-app [your-app-name]

At some point, and that doesn’t need to be today, we will realize that running this command gives us a lot of code and files that we probably will not ever use. I’m not going to cover the clean up process of each file but for reference and because pictures are worth 1000 words here is my file structure once I have removed the unnecessary files.

Once you do this your app will not function properly at first but that’s only because the app is looking for pictures/logos and testing files. We will have to delete a few lines of code but after going through this process a couple of times we’ll wonder how we worked through all that clutter before.

Again, it’s perfectly fine to leave the extra files in place. This was just a little bonus.

Next let’s add some directories to the app for organization. Namely ‘actions’, ‘components’, and ‘reducers’. We might consider adding a ‘containers’ folder to the app if it was going to be a larger application but we don’t need that for our purposes right now. We are going to use our App.js file to more or less function as our container for this app.

Then run npm i --save react-redux and npm i — save redux in the terminal to prepare our app for our dependencies that we will begin importing in the next step.

Setting Up Our Store

This is the wonderful thing about redux, The Store. It is essentially our state and can be accessed anywhere in the app and we only have to pass down a single prop.

In our index.js file add the following two imports:

import { createStore } from 'redux';
import { Provider } from 'react-redux';

“createStore” does just what we would expect, it creates a store(state) from our reducers. “Provider” provides that store to the rest of our application by wrapping our App component. We use these methods in the following way:

const store = createStore();ReactDom.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
document.getElementById('root')
);

For right now our store does not contain any state. We are going to fix that after we set up our actions.

Setting Up Our Actions

From the Redux documentation

Actions are plain JavaScript objects that have a type field. You can think of an action as an event that describes something that happened in the application.

Actions are quite straight forward and the trick is to name the type: field something that encapsulates what is happening in our application because that is going to make our future selves much happier, especially if you find yourself debugging this application.

First we will add a new file to our “actions” directory. I’m calling it counter.js because it will contain both the “increment” and “decrement” actions that we are going to write below:

const increment = (value) => {
return {
type: 'INCREMENTCOUNTER',
payload: value
}
}
const decrement = (value) => {
return {
type: 'DECREMENTCOUNTER',
payload: value
}
}
export { increment, decrement };

Setting Up Our Reducers

Now that we have our action to pass values to the reducers we can write our reducers that will update and return the state.

When setting up reducers the are a few key points to keep in mind. From the Redux documentation:

reducers must always follow some special rules:

They should only calculate the new state value based on the state and action arguments

They are not allowed to modify the existing state. Instead, they must make immutable updates, by copying the existing state and making changes to the copied values.

They must not do any asynchronous logic or other “side effects”

In other words our reducers must be ‘pure functions’, meaning the return value is based only on its inputs and has no other dependencies or effects on the overall program

So let’s add a new file to our reducers folder. I’ll call it counterReducer.js.

Here is how our file will look with our completed code:

export default function updateCounter(state = 0, action) {
switch(action.type) {
case 'INCREMENTCOUNTER':
return state + action.payload;
case 'DECREMENTCOUNTER':
return state - action.payload;
default:
return state;
}
}

In reality there is one reducer that imports all other reducer and sets up what our state will look like in our debugging process and how we will access our state within the application.

This reducer will be inside the reducers folder as well and I will name mine index.js .

The code in this file will look like this for our app:

import { combineReducers } from 'redux';
import counterReducer from 'counterReducer.js';
const allReducers = combineReducers({
counter: counterReducer
})
export default allReducers;

Tying It All Together

First we will go back to index.js at the top level of our src directory and add these lines of code:

import allReducers from './reducers/index';const store = createStore(
allReducers,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

The second part added to the store allows us to view the store in our developer tools extension as the wording implies, and it is crucial for debugging. Here is what our index.js file looks like now.

You can see that we are passing the store to App.js via the Provider that we imported from 'react-redux' .

Our App.js file looks like this:

You’ll see that I wrote a quick functional component to display what’s happening in our application. This is really the last piece to the puzzle.

Accessing State and Actions

To now access our state that we have been building we need two functions useSelector and useDispatch .

useSelecter allows us to access the state, in this case our counter. useDispatch allows use to access our actions, which are imported on the line below.

The Counter component looks like this:

Wrapping Up

And that is all. You can see that I am calling my actions and passing 1 as their arguments. I could pass any number in of course or grab a number from an input field.

For reference here is my file structure now:

and here is a video of the functioning app with the Redux store(state) updating and displaying in real time. The debugging tools on the left are possible because of our Redux extension and the extra lines of code we added in the store.

That is all. Good luck with your next React Redux application. I hope this video helps you out and feel free to leave comments in the area provided below or to email me at hyrum.butler3@gmail.com

--

--

Hyrum Butler

I love code! I love riddles! I love logic! Please reach out to me in regards to any of these topics.