React Redux Tutorial for Beginners: learning Redux in 2018

Published Jan 03, 2018Last updated Apr 24, 2018
React Redux Tutorial for Beginners: learning Redux in 2018

The simplest React Redux tutorial I wish I had when I started learning

When I first started learning Redux I wish I could find the simplest tutorial ever.

Despite the great resources out there I couldn’t wrap my head around some of the Redux concepts.

I knew what’s the state. But actions, action creators, and reducers? They were obscure for me.

Last but not least I didn’t know how to glue React and Redux together.

During those days I started writing my own React Redux tutorial and since then I learned a lot.

I taught myself the Redux fundamentals by writing this guide. I hope it’ll be useful for all those learning React and Redux.

Enjoy the reading!

React Redux tutorial: who this guide is for

The following React Redux guide is exactly what you're looking for if:

  • you have a good grasp of Javascript, ES6, and React
  • you're looking forward to learn Redux in the most simple way

React Redux tutorial: what you will learn

In the following guide you will learn:

  1. what is Redux
  2. how to use Redux with React

React Redux tutorial: a minimal React development environment

To follow along with the guide you should have a good grasp of Javascript, ES6, and React.

Also, create a minimal React development environment before starting off.

Feel free to use webpack 3 or Parcel.

To get started with Parcel follow Setting up React with Parcel or clone my Github repo:

git clone git@github.com:valentinogagliardi/minimal-react-parcel.git

If you prefer using webpack 3 follow How to set up React, Webpack 3, and Babel or clone my Github repo:

git clone git@github.com:valentinogagliardi/minimal-react-webpack.git

React Redux tutorial: what is the state?

To understand what is Redux you must first understand what is the state.

If you have ever worked with React the term state should be no surprise to you.

I guess you already wrote stateful React components like the following:

import React, { Component } from "react";

class ExampleComponent extends Component {
  constructor() {
    super();

    this.state = {
      articles: [
        { title: "React Redux Tutorial for Beginners", id: 1 },
        { title: "Redux e React: cos'è Redux e come usarlo con React", id: 2 }
      ]
    };
  }

  render() {
    const { articles } = this.state;
    return <ul>{articles.map(el => <li key={el.id}>{el.title}</li>)}</ul>;
  }
}

A stateful React component is basically a Javascript ES6 class.

Every stateful React component carries its own state. In a React component the state holds up data.

The component might render such data to the user.

And there's setState for updating the local state of a component.

Everybody learned React this way:

  1. render some data from the local state
  2. update the state with React setState

React Redux tutorial: what problem does Redux solve?

Now, it is fine to keep the state within a React component as long as the application remains small.

But things could become tricky in more complex scenarios.

You will end up with a bloated component filled with methods for managing and updating the state. The frontend shouldn’t know about the business logic.

Fine.

So what are the alternatives for managing the state of a React component? Redux is one of them.

Redux solves a problem that might not be clear in the beginning: it helps giving each React component the exact piece of state it needs.

Redux holds up the state within a single location.

Also with Redux the logic for fetching and managing the state lives outside React.

The benefits of this approach might be not so evident. Things will look clear as soon as you’ll get your feet wet with Redux.

In the next section we’ll see why you should learn Redux and when to use Redux within your applications.

React Redux tutorial: should I learn Redux?

Are you trying to learn Redux but you’re going nowhere?

Redux literally scares most beginners. But that shouldn’t be your case.

Redux is not that hard. The key is: don't rush learning Redux just because everybody is using it.

You should start learning Redux if you’re motivated and passionate about it.

Take your time.

I started to learn Redux because:

  • I was 100% interested in learning how Redux works
  • I was interested in brushing my React skills
  • I wanted to become a better React developer
  • the combination React/Redux is ubiquitous
  • Redux is framework agnostic. Learn it once, use it everywhere (Vue JS, Angular)

Rect Redux tutorial: should I use Redux?

It is feasible to build complex React application without even touching Redux. That comes at a cost.

Redux has a cost as well: it adds another layer of abstraction. But I prefer thinking about Redux as an investment, not as a cost.

Another common question for Redux beginners is: how do you know when you’re ready to use Redux?

If you think about it there is no rule of thumb for determining when you do need Redux for managing the state.

What I found is that you should consider using Redux when:

  • multiple React components needs to access the same state but do not have any parent/child relationship
  • you start to feel awkward passing down the state to multiple components with props

If that makes still no sense for you do not worry, I felt the same.

Dan Abramov says “Flux libraries are like glasses: you’ll know when you need them.”

And in fact it worked like that for me.

Dan Abramov has a nice write-up that will help you understand if your application needs Redux

There's also an interesting thread on dev.to with Dan explaining when is it time to stop managing state at the component level and switching to Redux

Make sure to take a look at Resources for learning Redux by Mark Erikson.

Oh by the way, Mark's blog is a treasure trove of Redux best practices.

Dave Ceddia shares its insight as well in What Does Redux Do? (and when should you use it?)

Before going further take your time to understand what problem does Redux solve and whether you’re motivated or not to learn it.

Be aware that Redux is not useful for smaller apps. It really shines in bigger ones. Anyway, learning Redux even if you're not involved in something big wouldn't harm anyone.

In the next section we’ll start building a proof of concept to introduce:

  • the Redux fundamental principles
  • Redux alongside with React

React Redux tutorial: getting to know the Redux store

Actions. Reducers. I kind of knew about them. But one thing wasn’t clear to me: how were all the moving parts glued together?

Were there some minions or what?

React Redux tutorial. There are no minions in Redux

The store orchestrates all the moving parts in Redux. Repeat with me: the store. The store in Redux is like the human brain: it’s kind of magic.

The Redux store is fundamental: the state of the whole application lives inside the store.

If you think about it Redux works the same as the human brain does. Everybody has memories (the state). And those memories lives within your brain (the store).

So to start playing with Redux we should create a store for wrapping up the state.

Move into your React development environment and install Redux:

cd minimal-react-webpack/
npm i redux --save-dev

Create a directory for holding the store:

mkdir -p src/js/store

Create a new file named index.js into src/js/store and finally initialize the store:

// src/js/store/index.js

import { createStore } from "redux";
import rootReducer from "../reducers/index";

const store = createStore(rootReducer);

export default store;

createStore is the function for creating the Redux store.

createStore takes a reducer as the first argument, rootReducer in our case.

You may also pass an initial state to createStore. But most of the times you don’t have to. Passing an initial state is useful for server side rendering. Anyway, the state comes from reducers.

NOTE: see Reducer returned undefined during initialization

What matters now is understanding what does a reducer do.

In Redux reducers produce the state. The state is not something you create by hand.

Armed with that knowledge let’s move on to our first Redux reducer.

React Redux tutorial: getting to know Redux reducers

While an initial state is useful for SSR in Redux the state must return entirely from reducers.

Cool but what's a reducer?

A reducer is just a Javascript function. A reducer takes two parameters: the current state and an action (more about actions soon).

The third principle of Redux says that the state is immutable and cannot change in place.

This is why the reducer must be pure. A pure function is one that returns the exact same output for the given input.

In plain React the local state changes in place with setState. In Redux you cannot do that.

Creating a reducer is not that hard. It's a plain Javascript function with two parameters.

In our example we'll be creating a simple reducer taking the initial state as the first parameter. As a second parameter we'll provide the action. As of now the reducer will do nothing than returning the initial state.

Create a directory for the root reducer:

mkdir -p src/js/reducers

Then create a new file named index.js into the src/js/reducers:

// src/js/reducers/index.js

const initialState = {
  articles: []
};

const rootReducer = (state = initialState, action) => state;

export default rootReducer;

I promised to keep this guide as simple as possibile. That's why our first reducer is a silly one: it returns the initial state without doing anything else.

Notice how the initial state is passed as a default parameter.

In the next section we’ll add an action to the mix. That’s where things will become interesting.

React Redux tutorial: getting to know Redux actions

Redux reducers are without doubt the most important concept in Redux. Reducers produce the state of the application.

But how does a reducer know when to produce the next state?

The second principle of Redux says the only way to change the state is by sending a signal to the store. This signal is an action. Dispatching an action is the process of sending out a signal.

Now, how do you change an immutable state? You won't. The resulting state is a copy of the current state plus the new data.

That's a lot to know.

The reassuring thing is that Redux actions are nothing more than Javascript objects. This is what an action looks like:

{
  type: 'ADD_ARTICLE',
  payload: { name: 'React Redux Tutorial for Beginners', id: 1 }
}

Every action needs a type property for describing how the state should change.

You can specify a payload as well. In the above example the payload is a new article. A reducer will add the article to the current state later.

It is a best pratice to wrap every action within a function. Such function is an action creator.

Let’s put everything together by creating a simple Redux action.

Create a directory for the actions:

mkdir -p src/js/actions

Then create a new file named index.js in src/js/actions:

// src/js/actions/index.js

export const addArticle = article => ({ type: "ADD_ARTICLE", payload: article });

So, the type property is nothing more than a string.

The reducer will use that string to determine how to calculate the next state.

Since strings are prone to typos and duplicates it’s better to have action types declared as constants.

This approach helps avoiding errors that will be difficult to debug.

Create a new directory:

mkdir -p src/js/constants

Then create a new file named action-types.js into the src/js/constants:

// src/js/constants/action-types.js

export const ADD_ARTICLE = "ADD_ARTICLE";

Now open up again src/js/actions/index.js and update the action to use action types:

// src/js/actions/index.js

import { ADD_ARTICLE } from "../constants/action-types";

export const addArticle = article => ({
  type: ADD_ARTICLE,
  payload: article
});

We're one step closer to have a working Redux application. Let's refactor our reducer!

React Redux tutorial: refactoring the reducer

Before moving forward let's recap the main Redux concepts:

  1. the Redux store is like a brain: it's in charge for orchestrating all the moving parts in Redux
  2. the state of the application lives as a single, immutable object within the store
  3. as soon as the store receives an action it triggers a reducer
  4. the reducer returns the next state

What's a Redux reducer made of?

A reducer is a Javascript function taking two parameters: the state and the action.

A reducer function has a switch statement (although unwieldy, a naive reducer could also use if/else).

The reducer calculates the next state depending on the action type. Moreover, it should return at least the initial state when no action type matches.

When the action type matches a case clause the reducer calculates the next state and returns a new object. Here's an excerpt of the code:

// ...
  switch (action.type) {
    case ADD_ARTICLE:
      return { ...state, articles: [...state.articles, action.payload] };
    default:
      return state;
  }
// ...

The reducer we created earlier does nothing than returning the initial state. Let's fix that.

Open up src/js/reducers/index.js and update the reducer as follow:

import { ADD_ARTICLE } from "../constants/action-types";

const initialState = {
  articles: []
};

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_ARTICLE:
      return { ...state, articles: state.articles.push(action.payload) };
    default:
      return state;
  }
};

export default rootReducer;

What do you see here?

Although it's valide code the above reducer breaks the main Redux principle: immutability.

Array.prototype.push is an impure function: it alters the original array.

Making our reducer complaint is easy. Using Array.prototype.concat in place of Array.prototype.push is enough to keep the initial array immutable:

import { ADD_ARTICLE } from "../constants/action-types";

const initialState = {
  articles: []
};

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_ARTICLE:
      return { ...state, articles: state.articles.concat(action.payload) };
    default:
      return state;
  }
};

export default rootReducer;

We're not done yet! With the spread operator we can make our reducer even better:

import { ADD_ARTICLE } from "../constants/action-types";

const initialState = {
  articles: []
};

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_ARTICLE:
      return { ...state, articles: [...state.articles, action.payload] };
    default:
      return state;
  }
};

export default rootReducer;

In the example above the initial state is left utterly untouched.

The initial articles array doesn't change in place.

The initial state object doesn't change as well. The resulting state is a copy of the initial state.

There are two key points for avoiding mutations in Redux:

The object spread operator is still in stage 3. Install Object rest spread transform to avoid a SyntaxError Unexpected token when using the object spread operator in Babel:

npm i --save-dev babel-plugin-transform-object-rest-spread

Open up .babelrc and update the configuration:

{
    "presets": ["env", "react"],
    "plugins": ["transform-object-rest-spread"]
}

Redux protip: the reducer will grow as your app will become bigger. You can split a big reducer into separate functions and combine them with combineReducers

In the next section we'll play with Redux from the console. Hold tight!

React Redux tutorial: Redux store methods

This will be super quick, I promise.

I want you to play with the brower's console for gaining a quick understanding of how Redux works.

Redux itself is a small library (2KB). The Redux store exposes a simple API for managing the state. The most important methods are:

  • getState for accessing the current state of the application
  • dispatch for dispatching an action
  • subscribe for listening on state changes

We will play in the brower's console with the above methods.

To do so we have to export as global variables the store and the action we created earlier.

Open up src/js/index.js and update the file with the following code:

import store from "../js/store/index";
import { addArticle } from "../js/actions/index";

window.store = store;
window.addArticle = addArticle;

Now run webpack dev server (or Parcel) with:

npm start

head over http://localhost:8080/ and open up the console with F12.

Since we've exported the store as a global variable we can access its methods. Give it a try!

Start off by accessing the current state:

store.getState()

output:

{articles: Array(0)}

Zero articles. In fact we haven't update the initial state yet.

To make things interesting we can listen for state updates with subscribe.

The subscribe method accepts a callback that will fire whenever an action is dispatched. Dispatching an action means notifying the store that we want to change the state.

Register the callback with:

store.subscribe(() => console.log("Look ma, Redux!!"))

To change the state in Redux we need to dispatch an action. To dispatch an action you have to call the dispatch method.

We have one action at our disposal: addArticle for adding a new article to the state.

Let's dispatch the action with:

store.dispatch( addArticle({ name: 'React Redux Tutorial for Beginners', id: 1 }) )

Right after running the above code you should see:

Look ma, Redux!!

To verify that the state changed run again:

store.getState()

The output should be:

{articles: Array(1)}

And that's it. This is Redux in its simplest form.

Was that difficult?

Take your time to explore these three Redux methods as an exercise. Play with them from the console:

  • getState for accessing the current state of the application
  • dispatch for dispatching an action
  • subscribe for listening on state changes

That's everything you need to know for getting started with Redux.

Once you feel confident head over the next section. We'll go straight to connecting React with Redux!

React Redux tutorial: connecting React with Redux

After learning Redux I realized it wasn't so complex.

I knew how to access the current state with getState.

I knew how to dispatch an action with dispatch

I knew how to listen for state changes with subscribe

Yet I didn’t know how to couple React and Redux together.

I was asking myself: should I call getState within a React component? How do I dispatch an action from a React component? And so on.

Redux on its own is framework agnostic. You can use it with vanilla Javascript. Or with Angular. Or with React. There are bindings for joining together Redux with your favorite framework/library.

For React there is react-redux.

Before moving forward install react-redux by running:

npm i react-redux --save-dev

To demonstrate how React and Redux work together we'll build a super simple application. The application is made of the following components:

  • an App component
  • a List component for displaying articles
  • a Form component for adding new articles

(The application is a toy and it does nothing serious other than displaying a list and a form for adding new items. Nonetheless it's still a good starting point for learning Redux)

React Redux tutorial: react-redux

react-redux is a Redux binding for React. It's a small library for connecting Redux and React in an efficient way.

The most important method you'll work with is connect

What does react-redux's connect do? Unsurprisingly it connects a React component with the Redux store.

You will use connect with two or three arguments depending on the use case. The fundamental things to know are:

  • the mapStateToProps function
  • the mapDispatchToProps function

What does mapStateToProps do in react-redux? mapStateToProps does exactly what its name suggests: it connects a part of the Redux state to the props of a React component. By doing so a connected React component will have access to the exact part of the store it needs.

What does mapDispatchToProps do in react-redux? mapDispatchToProps does something similar, but for actions. mapDispatchToProps connects Redux actions to React props. This way a connected React component will be able to dispatch actions.

Is everything clear? If not, stop and take your time to re-read the guide. I know it's a lot to learn and it requires time. Don't worry if you don't get Redux right know. It will click sooner or later.

In the next section we'll finally get our hands dirty!.

React Redux tutorial: App component and Redux store

We saw that mapStateToProps connects a portion of the Redux state to the props of a React component. You may wonder: is this enough for connecting Redux with React? No, it's not.

To start off connecting Redux with React we're going to use Provider.

Provider is an high order component coming from react-redux.

Using layman's terms, Provider wraps up your entire React application and makes it aware of the entire Redux's store.

Why so? We saw that in Redux the store manages everything. React must talk to the store for accessing the state and dispatching actions.

Enough theory.

Open up src/js/index.js, wipe out everything and update the file with the following code:

import React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import store from "../js/store/index";
import App from "../js/components/App";

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("app")
);

You see? Provider wraps up your entire React application. Moreover it gets the store as a prop.

Now let's create the App component since we're requiring it. It should be nothing special: App should import a List component and render itself.

I'm going to use some styling from Bootstrap 4 which I did include by default in the Webpack boilerplate. Anyway, feel free to use whichever library you like

Create a directory for holding the components:

mkdir -p src/js/components

and a new file named App.js inside src/js/components:

// src/js/components/App.js
import React from "react";
import List from "./List";

const App = () => (
  <div className="row mt-5">
    <div className="col-md-4 offset-md-1">
    <h2>Articles</h2>
      <List />
    </div>
  </div>
);

export default App;

Take moment and look at the component without the markup:

import React from "react";
import List from "./List";

const App = () => (
      <List />
);

export default App;

then move on to creating List.

React Redux tutorial: List component and Redux state

We have done nothing special so far.

But our new component, List, will interact with the Redux store.

A brief recap: the key for connecting a React component with Redux is connect.

Connect takes at least one argument.

Since we want List to get a list of articles it's a matter of connecting state.articles with the component. How? With mapStateToProps.

Create a new file named List.js inside src/js/components. It should look like the following:

// src/js/components/List.js

import React from "react";
import { connect } from "react-redux";

const mapStateToProps = state => {
  return { articles: state.articles };
};

const ConnectedList = ({ articles }) => (
  <ul className="list-group list-group-flush">
    {articles.map(el => (
      <li className="list-group-item" key={el.id}>
        {el.title}
      </li>
    ))}
  </ul>
);

const List = connect(mapStateToProps)(ConnectedList);

export default List;

The List component receives the prop articles which is a copy of the articles array. Such array lives inside the Redux state we created earlier. It comes from the reducer:

const initialState = {
  articles: []
};

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_ARTICLE:
      return { ...state, articles: [...state.articles, action.payload] };
    default:
      return state;
  }
};

Then it's a matter of using the prop inside JSX for generating a list of articles:

    {articles.map(el => (
      <li className="list-group-item" key={el.id}>
        {el.title}
      </li>
    ))}

React protip: take the habit of validating props with PropTypes

Finally the component gets exported as List. List is the result of connecting the stateless component ConnectedList with the Redux store.

A stateless component does not have its own local state. Data gets passed to it as props

Still confused? I was too. Understanding how connect works will take some time. Fear not, the road to learn Redux is paved with "ah-ha" moments.

I suggest taking a break for exploring both connect and mapStateToProps

Once you're confident about them head over the next section!

React Redux tutorial: Form component and Redux actions

The Form component we're going to create is a bit more complex than List. It's a form for adding new articles to our application.

Plus it is a stateful component.

A stateful component in React is a component carrying its own local state

A stateful component? "Valentino, we're talking about Redux for managing the state! Why on earth would you give Form its own local state??"

Even when using Redux it is totally fine to have stateful components.

Not every piece of the application's state should go inside Redux.

In this example I don't want any other component to be aware of the Form local state.

And that's perfectly fine.

What does the component do?

The component contains some logic for updating the local state upon a form submission.

Plus it receives a Redux action as prop. This way it can update the global state by dispatching the addArticle action.

Create a new file named Form.js inside src/js/components. It should look like the following:

// src/js/components/Form.js
import React, { Component } from "react";
import { connect } from "react-redux";
import uuidv1 from "uuid";
import { addArticle } from "../actions/index";

const mapDispatchToProps = dispatch => {
  return {
    addArticle: article => dispatch(addArticle(article))
  };
};

class ConnectedForm extends Component {
  constructor() {
    super();

    this.state = {
      title: ""
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({ [event.target.id]: event.target.value });
  }

  handleSubmit(event) {
    event.preventDefault();
    const { title } = this.state;
    const id = uuidv1();
    this.props.addArticle({ title, id });
    this.setState({ title: "" });
  }

  render() {
    const { title } = this.state;
    return (
      <form onSubmit={this.handleSubmit}>
        <div className="form-group">
          <label htmlFor="title">Title</label>
          <input
            type="text"
            className="form-control"
            id="title"
            value={title}
            onChange={this.handleChange}
          />
        </div>
        <button type="submit" className="btn btn-success btn-lg">
          SAVE
        </button>
      </form>
    );
  }
}

const Form = connect(null, mapDispatchToProps)(ConnectedForm);

export default Form;

What can I say about the component? Besides mapDispatchToProps and connect it's standard React stuff.

mapDispatchToProps connects Redux actions to React props. This way a connected component is able to dispatch actions.

You can see how the action gets dispatched in the handleSubmit method:

// ...
  handleSubmit(event) {
    event.preventDefault();
    const { title } = this.state;
    const id = uuidv1();
    this.props.addArticle({ title, id }); // Relevant Redux part!!
// ...
  }
// ...

Finally the component gets exported as Form. Form is the result of connecting ConnectedForm with the Redux store.

Side note: the first argument for connect must be null when mapStateToProps is absent like in the Form example. Otherwise you'll get TypeError: dispatch is not a function.

Our components are all set!

Update App to include the Form component:

import React from "react";
import List from "./List";
import Form from "./Form";

const App = () => (
  <div className="row mt-5">
    <div className="col-md-4 offset-md-1">
      <h2>Articles</h2>
      <List />
    </div>
    <div className="col-md-4 offset-md-1">
      <h2>Add a new article</h2>
      <Form />
    </div>
  </div>
);

export default App;

Now run webpack (or Parcel) with:

npm start

and head over to http://localhost:8080

You should see the following working POC:

React Redux tutorial demo. Nothing fancy but still useful for showing React and Redux at work

Nothing fancy but still useful for showing React and Redux at work!

The List component on the left is connected to the Redux store. It will re-render whenever you add a new article.

React Redux demo

Whoaaa!

You can find the code for that silly app (with prop-types and a splitted reducer) on my Github repo.

React Redux tutorial: wrapping up

I hope you'll learn something from this guide. I tried my best to keep things as simple as possibile. I would love to hear your feedback in the comments below!

Redux has a lot of boilerplate and moving parts. Don't get discouraged. Pick Redux, play with it and take your time to absorb all the concepts.

I went from zero to understanding Redux by small steps. You can do it too!

Also, take your time to investigate why and if you should use Redux in your application.

Either way think of Redux as an investment: learning it is 100% worthwile.

Redux is not a universal solution for state management. Mobx emerged as an interesting alternative to Redux. I've been watching Apollo Client too. Who will win? Only time will tell.

React Redux tutorial: resources for learning functional programming

Redux scares most beginners because it revolves around functional programming and pure functions.

Suggestings some resources is the best I can do since functional programming is beyond the scope of this guide. These are the best places for learning more about functional programming and pure functions:

Professor Frisby's Mostly Adequate Guide to Functional Programming by Brian Lonsdorf

Functional-Light Javascript by Kyle Simpson

React Redux tutorial: async actions in Redux

I wasn't sure whether talking about async actions would have been appropriate or not.

Most Redux beginners struggle to learn plain Redux. Handling async actions in Redux is not a straighforward task so better not overcomplicate things.

When you'll feel confident about the core Redux concepts go check A Dummy’s Guide to Redux and Thunk in React by Matt Stow. It's a nice introduction to handling API calls in Redux with redux-thunk.

Thanks for reading and happy coding!

Originally published on valentinog.com/blog on January 2, 2018

Discover and read more posts from Valentino Gagliardi
get started