React Redux Tutorial for Beginners: The Definitive Guide (2019)

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

React Redux tutorial for beginners

When I first started learning Redux I wish I had some “Redux for dummies”. I felt dumb because I couldn’t wrap my head around actions, action creators, reducers. And how about middleware? You’ve got to be kidding me!

So during those days I started teaching Redux for the sake of learning more, while writing my own React Redux tutorial. Since then I learned a lot and this React Redux tutorial is an effort for helping you too to learn Redux, in the most simplest way.

Enjoy the reading!

React Redux tutorial: who this guide is for

The following React Redux guide is for JavaScript developers with a good grasp of ES6 and React. There are countless React tutorials online if you want to refresh your understandings, but if you’re just starting out I suggest reading Getting Started with React by Tania Rascia.

If you want to refresh your JavaScript skills before or after taking this tutorial check out my “Little JavaScript Book”, available for free on Github or as a PDF/ePub/Mobi.

React Redux tutorial: what you will learn

The guide covers mostly Redux with React because of the wide adoption of this combination but Redux can also be used as a stand-alone library without any frontend framework/library.

So in the following guide you will learn:

  • what is Redux
  • Redux’s building blocks
  • how to use Redux stand-alone
  • how to use Redux with React

React Redux tutorial: a minimal React development environment

Before starting off make sure you have a React development environment in place.

To make one you can follow How to set up React, webpack, and Babel or even better, use create-react-app:

npx create-react-app react-redux-tutorial

Once done you’re good to go.

React Redux tutorial: what is the state?

What is Redux? To answer that question we must first talk about state in JavaScript web applications. Consider a simple user flow:

“as a user I can click a button named Click me and a modal should appear soon after”.

Guess what, even in this trivial interaction there is a state we must deal with. For example, we can describe the initial state of the app as a plain JavaScript object:

const state = {
  buttonClicked: 'no',
  modalOpen: 'no'
}

When the user clicks, the state changes and we have:

const state = {
  buttonClicked: 'yes',
  modalOpen: 'yes'
}

How do you reliably keep track of these state changes? What if the state is mutated by accident by some unrelated piece of logic? Is there a library that can help us?

Also, if you worked with React before the term state should be no surprise to you. I guess you already wrote some “stateful” React component like this:

import React, { Component } from "react";

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

    this.state = {
      articles: [
        { title: "React Redux Tutorial for Beginners", id: 1 },
        { title: "TypeScript tutorial for beginners", 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 a JavaScript class (with React hooks that’s no longer the case).

In a React component the state holds data which can be rendered to the user. The state in React could also change in response to actions and events: in fact you can update the local component’s state with setState().

So, in general a typical JavaScript application is full of state. For example, state is:

  • what the user sees (data)
  • the data we fetch from an API
  • the URL
  • the items selected inside a page
  • eventual errors to show to the user

Having seen the basics let’s now talk about what problem Redux tries to solve.

What problem does Redux solve?

So, state is everywhere in web applications. From now on I’ll talk about state and logic in the context of a typical React application, but consider these concept applicable to any frontend architecture, regardless of the specific library. The thing is, can you imagine how much state a web application application has?

Even an innocent single page app could grow out of control without clear boundaries between every layer of the application. This holds particularly true in React.

Yeah, you can get by with keeping the state within a parent React component (or in context) as long as the application remains small. Then things will become tricky especially when you add more behaviours to the app. At some point you may want to reach for a consistent way to keep track of state changes. Not only, I’d say that frontend components shouldn’t know about the business logic. Ever.

Unfortunately a ton of logic gets stuffed into frontend components these days. Is there an alternative to this agony?

Redux can solve exactly those problems. It might not be clear in the beginning, but Redux helps giving each frontend component the exact piece of state it needs.

Even better, Redux can hold business logic inside its own layer (middleware), alongside with the code for fetching data. The benefits of this approach are manifold.

In the next sections we’ll see when and how to use Redux in your applications. But first a couple of words about the quintessential question: “should I use Redux”?

React Redux tutorial: should I use Redux?

I must admit I’m a bit biased here because I’m fond of Redux and I suggest it whenever I join a new project. But maybe you don’t need neither Redux, nor alternatives like Mobx and friends. Even more if you’re working on a simple project.

In React for example there are many ways to avoid using Redux: children props, the context API.

But for medium to bigger projects I always found Redux (or an equivalent) almost mandatory: state management libraries beautifully keep logic and behaviours abstracted away from the UI. UI testability skyrockets and so developer productivity. But if you look at it from another perspective you may argue that Redux has a cost. It adds another layer of abstraction to your application.

What cost are you willing to pay? Convoluted frontend components or multiple layers of abstractions?

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

  • Redux fundamental principles
  • Redux alongside with React

Again, make sure you have a React development environment ready to use!

React Redux tutorial: getting to know the Redux store

When I approached Redux for the first time I was confused. There is too much terminology: action, reducer, middleware. But on top of that it wasn’t clear to me how were all the moving parts glued together? There were some minions or what? In Redux there are no minions (unfortunately).

What orchestrates all the cogs is the store. Repeat with me: the store. The store in Redux is kind of magic and holds all of the application’s state.

So let’s create a store to start playing with Redux. Move into your React development environment and install Redux:

cd react-redux-tutorial

npm i redux --save-dev

Create a directory for the store:

mkdir -p src/js/store

Next up create a new file, src/js/store/index.js and initialize the store:

// src/js/store/index.js

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

const store = createStore(rootReducer);

export default store;

As you can see, store is the result of calling createStore, a function from the Redux library. createStore takes a reducer as the first argument and in our case we passed in rootReducer (not yet present).

You may also pass an initial state to createStore, useful for server side rendering and state preloading, but for now we’re not interested in that. The most important concept to understand here is that the state in Redux comes from reducers. Let’s repeat: reducers produce the state of your application.

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

See the branch on Github

React Redux tutorial: getting to know Redux reducers

What’s a reducer? A Redux reducer is just a JavaScript function. It takes two parameters: the current state and action (more about actions soon).

In a typical React component the local state might be mutated in place. In Redux you’re not allowed to do that. The third principle of Redux (as outlined by its creator) prescribes that the state is immutable and cannot change in place.

In other words the reducer must be pure. A pure function is one that returns the exact same output for the given input. But despite this terminology reasoning about a reducer is not that hard.

In our example we’ll be creating a simple reducer which takes initial state ad action as parameters. Create a directory for the root reducer:

mkdir -p src/js/reducers

Then create a new file, src/js/reducers/index.js:

const initialState = {
  articles: []
};

function rootReducer(state = initialState, action) {
  return state;
};

export default rootReducer;

Notice how the initial state is passed as a default parameter. But as of now our reducer does nothing than returning the initial state.

In the next section we’ll add an action to the mix, and things will become interesting.

See the branch on Github

React Redux tutorial: getting to know Redux actions and named constants

Redux reducers are without doubt the most important concept in Redux. Reducers produce the state of an application. But how does a reducer know when to generate 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. So “dispatching an action” means sending out a signal to the store.

Confused? The reassuring thing is that Redux actions are nothing more than JavaScript objects. This is how an action looks like:

{
  type: 'ADD_ARTICLE',
  payload: { title: 'React Redux Tutorial', id: 1 }
}

As you can see it’s a JavaScript object with two properties: type and payload.

The type property drives how the state should change and it’s always required by Redux. The payload property instead describes what should change, and might be omitted if you don’t have new data to save in the store.

As a best practice in Redux we wrap every action within a function, so that object creation is abstracted away. Such function takes the name of action creator: let’s put everything together by creating a simple action creator.

Create a directory for actions:

mkdir -p src/js/actions

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

// src/js/actions/index.js

export function addArticle(payload) {
  return { type: "ADD_ARTICLE", payload }
};

You can notice that the type property is a string. Strings are prone to typos and duplicates and for this reason it’s better to declare actions as constants. Create a new folder for them:

mkdir -p src/js/constants

Then create a new file, src/js/constants/action-types.js:

// 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 function addArticle(payload) {
  return { type: ADD_ARTICLE, payload };
}

As you can see we’re starting to deal with multiple files. That’s the main pet peeve with Redux for most people. You can follow the Redux duck convention if you want, it keeps every Redux related piece in a single file.

One step closer to have a working Redux application, but first we need to tweak the reducer for catching the new action.

See the branch on Github

Refactoring the reducer

We left last section with the following question: how does a reducer know when to generate the next state? The key here is the Redux store. When an action is dispatched, the store forwards a message (the action object) to the reducer.

At this point the reducer says “oh, let’s look at the type property of this action”. Then depending on the action type, the reducer produces the next state, eventually merging the action payload into the new state.

Earlier we created a reducer that does nothing. Let’s fix it! Open up src/js/reducers/index.js and update the reducer with an if statement for checking the action type:

// src/js/reducers/index.js

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

const initialState = {
  articles: []
};

function rootReducer(state = initialState, action) {
  if (action.type === ADD_ARTICLE) {
    state.articles.push(action.payload);
  }
  return state;
}

export default rootReducer;

There is also a line of code which pushes the action payload into the initial state. Seems the right thing to do. But it’s wrong! Our reducer breaks the main Redux principle: immutability.

Array.prototype.push is an impure function: it modifies the original array. But there’s more. We’re also changing the initial state in place.

We need a fix. First we can return a new state with Object.assign, that is, a new JavaScript object. This way we keep the original state unaltered. Then we can use Array.prototype.concat in place of Array.prototype.push for keeping the original array:

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

const initialState = {
  articles: []
};

function rootReducer(state = initialState, action) {
  if (action.type === ADD_ARTICLE) {
    return Object.assign({}, state, {
      articles: state.articles.concat(action.payload)
    });
  }
  return state;
}

export default rootReducer;

Now the initial state is left in pristine conditions and the resulting state is just a copy of the initial state. Remember two key points for avoiding mutations in Redux:

  • use concat(), slice(), or the spread operator for arrays
  • use Object.assign() or object spread of objects

If this stuff about immutability feels boilerplate to you, redux starter kit has solved the problem. Take a look at it once you finish this tutorial.

In the next section we’ll play with Redux from the browser’s console. Hold tight!

See the branch on Github

React Redux tutorial: Redux store methods

This will be super quick, I promise.

You might be surprised to know that Redux itself is a small library (2KB) and the most important methods are just three:

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

We will play in the browser’s console with them. To do so we need to export the store and the action we created as global variables. Create a new file named src/js/index.js and place there the following code:

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

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

Now open up src/index.js as well, clean up its content and update it as follows:

import index from "./js/index";

Now run the development server with:

npm start

head over http://localhost:8080/ and open up the console with F12. Start off by reading 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 we’ll call the dispatch method. We have one action for now: addArticle for adding a new item to the state. Let’s dispatch the action with:

store.dispatch( addArticle({ title: '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();
// output: {articles: Array(1)}

And that’s it. This is Redux in its simplest form. Was that difficult?

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 and 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 from React? How do I dispatch an action from a React component? And so on.

Redux 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, a library for which you need to learn just one method for now: connect. What does it 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:

  • a mapStateToProps function (you can name it also “select”)
  • a mapDispatchToProps function

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.

mapDispatchToProps does something similar, but for actions. mapDispatchToProps connects Redux actions to React props. This way a connected React component will be able to send messages to the store.

In the next section we’ll finally get our hands dirty. We’ll build a super simple application made of three components:

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

React Redux tutorial: App component and Redux store

Before starting off install react-redux with:

npm i react-redux --save-dev

I said 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. We also need Provider, an high order component from react-redux.

Open up src/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("root")
);

As you can see Provider wraps up your React application and makes it aware of the entire Redux’s store.

Now let’s create the App component. It’s nothing special: App should import a List component and render itself. Create a directory for holding components:

mkdir -p src/js/components

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

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

const App = () => (
  <div>
    <h2>Articles</h2>
      <List />
  </div>
);

export default App;

Save and close the file, 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. Note that “mapStateToProps” is just a convention, most developers for example use “select”.

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

// 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>
    {articles.map(el => (
      <li 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 we saw in the Redux state. It comes from the reducer:

const initialState = {
  articles: []
};

function rootReducer(state = initialState, action) {
  if (action.type === ADD_ARTICLE) {
    return Object.assign({}, state, {
      articles: state.articles.concat(action.payload)
    });
  }
  return state;
}

Always remember: the state in redux comes from reducers.

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

Still confused? Understanding how connect works will take some time. But fear not, the road to learn Redux is paved with “ah-ha” moments.

I suggest taking a break for exploring both connect and mapStateToProps.

Head over the next section when you’re ready!

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 items to our application and for that we’ll use a JavaScript class.

Disclaimer: this tutorial was born when React didn’t have hooks yet. I could use a functional component here, but to avoid twisting the tutorial I’ll stick with classes.

The class component will help keeping some local state, like form inputs. It has also logic for updating the local state on form submission.

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

Create a new file in src/js/components/Form.js with the following code:

// src/js/components/Form.js

import React, { Component } from "react";
import { connect } from "react-redux";
import { addArticle } from "../actions/index";

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

class ConnectedForm extends Component {
  constructor(props) {
    super(props);
    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;
    this.props.addArticle({ title });
    this.setState({ title: "" });
  }
  render() {
    const { title } = this.state;
    return (
      <form onSubmit={this.handleSubmit}>
        <div>
          <label htmlFor="title">Title</label>
          <input
            type="text"
            id="title"
            value={title}
            onChange={this.handleChange}
          />
        </div>
        <button type="submit">SAVE</button>
      </form>
    );
  }
}

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

export default Form;

A brief explanation of the component:

  • besides mapDispatchToProps and connect it’s standard React stuff
  • mapDispatchToProps connects Redux actions to React props
  • the action is dispatched in the handleSubmit method

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

Note: the first argument for connect must be null when mapStateToProps is absent like in our example. Or you’ll get TypeError: dispatch is not a function.

Our components are all set! Now update App to include the Form component:

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

const App = () => (
  <>
    <div>
      <h2>Articles</h2>
      <List />
    </div>
    <div>
      <h2>Add a new article</h2>
      <Form />
    </div>
  </>
);

export default App;

Run the development server with:

npm start

and you should see our working proof of concept (in the first version of this tutorial I used Bootstrap, then removed):

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 item.

You did it! But we’re not done yet! In the next section we’ll look at Redux middleware. Hold tight!

See the branch on Github

React Redux tutorial: what is a Redux middleware?

So far we saw the building blocks of Redux: store, the traffic policeman in Redux. The reducer, which makes the state in Redux.

Then there are actions, plain JavaScript objects, acting as messengers in your application. Finally we have action creators, functions for creating those messages.

Now, imagine the following scenario: you need to prevent users from creating articles with particular words inside the title. Let’s take a look at handleSubmit in Form.js:

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

We can just add a check before this.props.addArticle right? It could be something like:

  handleSubmit(event) {
    event.preventDefault();
    const { title } = this.state;
    const forbiddenWords = ['spam', 'money'];
    const foundWord = forbiddenWords.filter(word => title.includes(word) )
    if (foundWord) {
      return this.props.titleForbidden();
    }
    this.props.addArticle({ title });
    this.setState({ title: "" });
  }

But wasn’t the entire point of Redux to move the logic out of our React components? Yes! So what? Can we check the title property inside the reducer? Maybe! And while we’re there let’s dispatch another action in response to a forbidden word. But how I’m supposed to access dispatch inside a reducer?

It’s clear that we want to reach for something different. Looks like we want to check the action payload (and the title property) before the action is passed to the reducer. There should be a way for tapping into the application’s flow. And guess what, that’s exactly what a Redux middleware does.

A Redux middleware is a function that is able to intercept, and act accordingly, our actions, before they reach the reducer. And while the theory is quite simple, a Redux middleware can look a bit confusing. In its basic form a Redux middleware is a function returning a function, which takes next as a parameter. Then the inner function returns another function which takes action as a parameter and finally returns next(action). Here’s how it looks like:

function forbiddenWordsMiddleware() {
  return function(next){
    return function(action){
      // do your stuff
      return next(action);
    }
  }
}

I know, you want to cry and change career but bear with me. Middlewares in Redux are super important because they will hold the bulk of your application’s logic. If you think about it there is no better place than a middleware for abstracting away business logic. And the nice thing is that while inside the middleware you can access getState and dispatch, like so:

function forbiddenWordsMiddleware({ getState, dispatch }) {
  return function(next){
    return function(action){
      // do your stuff
      return next(action);
    }
  }
}

Armed with that knowledge we can create your first Redux middleware: it should check whether the action’s payload has bad words into it. We’ll see the actual implementation into the next section.

React Redux tutorial: your first Redux middleware

The middleware we’re going to build should inspect the action’s payload. There are a lot of benefits from using a Redux middleware:

  • most of the logic can live outside the UI library
  • middlewares become reusable pieces of logic, easy to reason about
  • middlewares can be tested in isolation

So, let’s get our hands dirty. Create a new folder for the middleware:

mkdir -p src/js/middleware

Now create a new file named index.js in src/js/middleware. The structure of our first middleware should be like:

function forbiddenWordsMiddleware({ dispatch }) {
  return function(next){
    return function(action){
      // do your stuff
      return next(action);
    }
  }
}

For now we don’t need getState, we just get dispatch as the first parameter. Nice. Now we need to check the action payload, namely the title property. If the title matches one or more bad words we stop the user from adding the article.

Also, the check should fire up only when the action is of type ADD_ARTICLE. It makes sense. How about this one:

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

const forbiddenWords = ["spam", "money"];

export function forbiddenWordsMiddleware({ dispatch }) {
  return function(next) {
    return function(action) {
      // do your stuff
      if (action.type === ADD_ARTICLE) {

        const foundWord = forbiddenWords.filter(word =>
          action.payload.title.includes(word)
        );

        if (foundWord.length) {
          return dispatch({ type: "FOUND_BAD_WORD" });
        }
      }
      return next(action);
    };
  };
}

Here’s what the middleware does: when action type is ADD_ARTICLE check if action.payload.title contains a bad word. If it does then dispatch an action of type “FOUND_BAD_WORD”, otherwise let the next action pass.

And this last point is really important: you should always return next(action) in your middleware. If you forget to return next(action) the application will stop, and no other action will reach the reducer.

Now, time to wire up forbiddenWordsMiddleware to the Redux store. For that we need to import our middleware, another utility from Redux (applyMiddleware), and then cook everything together.

Open up src/js/store/index.js and modify the file like so:

// src/js/store/index.js

import { createStore, applyMiddleware } from "redux";
import rootReducer from "../reducers/index";
import { forbiddenWordsMiddleware } from "../middleware";

const store = createStore(
  rootReducer,
  applyMiddleware(forbiddenWordsMiddleware)
);

export default store;

Note: if you want to enable Redux Dev Tools use this code.

Save and close the file, run npm start and check if the middleware works. Try to add an article with “money” in its title and you won’t see the new article appear in the list.

The middleware works! Good job! In the next sections we’ll explore asynchronous actions in Redux with Redux Thunk and Redux Saga.

See the branch on Github

React Redux tutorial: asynchronous actions in Redux, the naive way

So far we were dealing with synchronous data. That is, dispatching an action is synchronous. No AJAX, no promises. We return a plain object from our action creators. And when the action reaches the reducer we return the next state.

Now, suppose we want to fetch data from an API. In React you would put a call in componentDidMount and call it a day. But how about Redux? What’s a good place for calling asynchronous functions? Let’s think a moment about it.

Reducers? No way. Reducers should stay lean and clean. A reducer is not a good place for asynchronous logic.

Actions? How I am supposed to do that? Actions in Redux are plain objects. And how about action creators? An action creator is a function, and it looks like a nice spot for calling an API! Let’s give it a shot.

We’ll create a new action named getData. This action calls an API with fetch and returns a Redux action.

Open up src/js/actions/index.js and create a new action named getData:

// src/js/actions/index.js

// ...
// our new action creator. Will it work?
export function getData() {
  return fetch("https://jsonplaceholder.typicode.com/posts")
    .then(response => response.json())
    .then(json => {
      return { type: "DATA_LOADED", payload: json };
    });
}

It makes sense. But will it work? Let’s wire up a React component so it dispatches getData from componentDidMount. mapDispatchToProps (this time with the object shorthand form) will map Redux action creators to our component’s props. Create a new React component in src/js/components/Posts.js:

import React, { Component } from "react";
import { connect } from "react-redux";
import { getData } from "../actions/index";

export class Post extends Component {
  componentDidMount() {
    // calling the new action creator
    this.props.getData();
  }

  render() {
    return null;
  }
}

export default connect(
  null,
  { getData }
)(Post);

Finally update src/js/components/App.js to use the new component:

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

const App = () => (
  <>
    <div>
      <h2>Articles</h2>
      <List />
    </div>
    <div>
      <h2>Add a new article</h2>
      <Form />
    </div>
    <div>
      <h2>API posts</h2>
      <Post />
    </div>
  </>
);

export default App;

Save and close the files, run the app, and look at the browser. You’ll see: “Error: Actions must be plain objects. Use custom middleware for async actions“.

In fact we cannot call fetch from within an action creator in Redux. Now what?

For making things work we need a custom middleware. Luckily there’s something ready for us: redux-thunk.

Asynchronous actions in Redux with Redux Thunk

We just learned that calling fetch from an action creator does not work. That’s because Redux is expecting objects as actions but we’re trying to return a Promise. With redux-thunk we can overcome the problem and return functions from action creators. Inside that function we can call APIs, delay the dispatch of an action, and so on.

First we need to install the middleware with:

npm i redux-thunk --save-dev

Now let’s load the middleware in src/js/store/index.js:

import { createStore, applyMiddleware, compose } from "redux";
import rootReducer from "../reducers/index";
import { forbiddenWordsMiddleware } from "../middleware";
import thunk from "redux-thunk";

const storeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
  rootReducer,
  storeEnhancers(applyMiddleware(forbiddenWordsMiddleware, thunk))
);

export default store;

At this point we need to refactor getData to use redux-thunk. Open up src/js/actions/index.js and update the action creator like so:

export function getData() {
  return function(dispatch) {
    return fetch("https://jsonplaceholder.typicode.com/posts")
      .then(response => response.json())
      .then(json => {
        dispatch({ type: "DATA_LOADED", payload: json });
      });
  };
}

That’s redux-thunk!

A few things worth noting in the new version of getData: the fetch call gets returned from an outer function and the outer function has dispatch as a parameter (basically it’s a JavaScript closure). If you want to access the state inside the action creator you can add getState in the parameter’s list.

Also, notice the use of dispatch inside “then”. We need to explicitly call dispatch inside the async function for dispatching the next action.

With that in place we’re ready to update our reducer with the new action type. Open up src/js/reducers/index.js and add a new if statement. We can also add a new key inside initialState for saving the articles from the API:

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

const initialState = {
  articles: [],
  remoteArticles: []
};

function rootReducer(state = initialState, action) {
  if (action.type === ADD_ARTICLE) {
    return Object.assign({}, state, {
      articles: state.articles.concat(action.payload)
    });
  }

  if (action.type === "DATA_LOADED") {
    return Object.assign({}, state, {
      remoteArticles: state.remoteArticles.concat(action.payload)
    });
  }
  return state;
}

export default rootReducer;

(I know, DATA_LOADED should be its own named costant. I left it as an exercise for you. Hope you don’t mind!)

Finally we’re ready to update our Post component for displaying our “remote” posts. We will use mapStateToProps (again, feel free to call this function select) for selecting ten posts:

import React, { Component } from "react";
import { connect } from "react-redux";
import { getData } from "../actions/index";

export class Post extends Component {
  componentDidMount() {
    this.props.getData();
  }

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

function mapStateToProps(state) {
  return {
    articles: state.remoteArticles.slice(0, 10)
  };
}

export default connect(
  mapStateToProps,
  { getData }
)(Post);

Save and close the files, run the app, and everything should work fine! Good job!

To recap: Redux does not understand other types of action than a plain object. If you want to move asynchronous logic from React to Redux and being able to return functions instead of plain objects you have to use a custom middleware.

redux-thunk is a middleware for Redux. With redux-thunk you can return functions from action creators, not only objects. You can do asynchronous work inside your actions and dispatch other actions in response to AJAX calls.

When to use redux-thunk? redux-thunk is a nice middleware that works very well for simpler use cases. But if your asynchronous logic involves more complex scenarios then redux saga might be a better fit.

In the next section we’ll take a look at it. Hold tight!

See the branch on Github

React Redux tutorial: introducing Redux Saga

redux-thunk makes perfect sense for a lot of project. You can also entirely skip redux-thunk and move your asynchronous logic to a custom middleware. But in reality asynchronous actions can be trickier to test and organize.

For this reason most developers prefer an alternative approach: redux saga.

What is redux saga? redux saga is a Redux middleware for managing side effects. With redux saga you can have a separate thread in your application for dealing with impure actions: API calls, storage access, and more.

redux saga is different from an async action in terms of both syntax and code organization. With redux thunk you can put an API call directly inside an action creator while in redux saga you can have clear separation between synchronous and asynchronous logic. And that logic will be totally separated from your Redux code.

Redux saga does not use regular JavaScript function. You will see a lot of asterisks and “yield” in your sagas.

Those asterisks mark generator functions!

Generator functions in JavaScript are function which can be paused and resumed on demand. redux saga relies heavily on generator functions but the good thing is that you won’t need to call next() in your code. redux saga handles that for you under the hood.

Writing your first Redux Saga

In this section we will refactor our code to use a Redux saga instead of a thunk. I won’t cover the entire Saga API in this post so please bear with me. We’ll just take a look at a bunch of methods.

Before getting started install redux saga with:

npm i redux-saga --save-dev

Now we can refactor our async action and remove the fetch call. From now on our action creator will just dispatch a plain action. Open up src/js/actions/index.js and modify getData to return a plain action named DATA_REQUESTED:

export function getData() {
  return { type: "DATA_REQUESTED" };
}

The DATA_REQUESTED action will be intercepted by Redux saga with the takeEvery method. You can imagine takeEvery taking every DATA_REQUESTED action passing inside our app and starting some work in response to that action.

Now, how do you structure a saga? A redux saga could live in a single file containing:

  • a worker function
  • a watcher function

The watcher is a generator function watching for every action we are interested in. In response to that action, the watcher will call a worker saga, which is another generator function for doing the actual API call.

The worker saga will call the remote API with the call method from redux-saga/effects. When the data is loaded we can dispatch another action from our saga with the put method, again, from redux-saga/effects. Makes sense?

Armed with this knowledge we can lay down our first redux saga! First create a new folder for holding your sagas:

mkdir -p src/js/sagas

Then create a new file named api-saga.js in src/js/sagas. And here’s our saga:

import { takeEvery, call, put } from "redux-saga/effects";

export default function* watcherSaga() {
  yield takeEvery("DATA_REQUESTED", workerSaga);
}

function* workerSaga() {
  try {
    const payload = yield call(getData);
    yield put({ type: "DATA_LOADED", payload });
  } catch (e) {
    yield put({ type: "API_ERRORED", payload: e });
  }
}

Let’s take a break to read through the logic flow of our saga.

Demystifying your first redux saga

Take a look at the code above. Here’s how it works:

  1. take every action named DATA_REQUESTED and for each action spin a worker saga
  2. inside the worker saga call a function named getData
  3. if the function succeeds, then dispatch (put) a new action named DATA_LOADED alongside with a payload
  4. if the function errors out, then dispatch (put) a new action named API_ERRORED, alongside with a payload (the error)

The only thing we’re missing in our code is the getData function. Open up src/js/sagas/api-saga.js again and add the function:

import { takeEvery, call, put } from "redux-saga/effects";

export default function* watcherSaga() {
  yield takeEvery("DATA_REQUESTED", workerSaga);
}

function* workerSaga() {
  try {
    const payload = yield call(getData);
    yield put({ type: "DATA_LOADED", payload });
  } catch (e) {
    yield put({ type: "API_ERRORED", payload: e });
  }
}

function getData() {
  return fetch("https://jsonplaceholder.typicode.com/posts").then(response =>
    response.json()
  );
}

And finally we can wire up redux saga to our redux store. Open up src/js/store/index.js and update the store as follows:

import { createStore, applyMiddleware, compose } from "redux";
import rootReducer from "../reducers/index";
import { forbiddenWordsMiddleware } from "../middleware";
import createSagaMiddleware from "redux-saga";
import apiSaga from "../sagas/api-saga";

const initialiseSagaMiddleware = createSagaMiddleware();

const storeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
  rootReducer,
  storeEnhancers(
    applyMiddleware(forbiddenWordsMiddleware, initialiseSagaMiddleware)
  )
);

initialiseSagaMiddleware.run(apiSaga);

export default store;

Worth noting, the createSagaMiddleware method and initialiseSagaMiddleware.run for running our saga. Now close and save the file. Run npm start and You should see the exact same output again with the remote posts correctly displaying in the browser.

Congratulations! You created your first redux saga! And now a couple of exercises for you:

  • our reducer was ready for handling DATA_LOADED alongside with its payload. Complete the reducer for dealing with API_ERRORED.
  • move DATA_LOADED, API_ERRORED, and DATA_REQUESTED inside named constants.
  • do we need to better account for fetch errors inside getData?

CODE: you can access the complete example at react-redux-tutorial on Github. Clone the repo and checkout the most recent branch:

git clone https://github.com/valentinogagliardi/react-redux-tutorial
cd react-redux-tutorial
git checkout your-first-redux-saga

See the branch on Github

Redux: where are we now?

The Redux ecosystem is evolving. A couple of new APIs appeared since I first wrote this guide.

First, react-redux gained hooks. It’s an alternative to using connect() for wiring your React components with Redux. The new API is completely optional, suited for new React codebases relaying exclusively on functional components and hooks.

A more interesting news is the rise of redux-starter-kit, an opinionated layer over the infamous Redux boilerplate. Check it out!

Wrapping up

What a journey! I hope you learned something from this guide. I tried my best to keep things as simple as possible. 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% worthwhile.

Thanks for reading and stay tuned on this blog!

Need JavaScript training for your team?

399 Replies to “React Redux Tutorial for Beginners: The Definitive Guide (2019)”

      1. Thanks for the hard work on the tutorial Valentino! Can you please fix the errors Julia mentioned below, as this is supposed to be a beginner’s tutorial, but most beginners will get lost when they encounter these issues and not be able to complete it? It took me a while to debug the arrow functions one – I was able to with this answer, but I’m sure there’s a newer way: https://stackoverflow.com/questions/42046496/cant-get-arrow-functions-to-work-react-babel-webpack-es6. Thank you!

        1. Hi Ivan

          are you talking about this? “using arrow functions to bind methods didn’t work”. There are no arrow function for binding methods in the tutorial. handleChange and handleSubmit are regular class methods.

      2. the explaination for the connect function was not sufficient. I could not understand whats really happening in the connectedList function.

  1. Just finished the tutorial, it was extremely helpful in breaking everything into discrete steps. + so many upvotes! As a beginner, it was great to see everything explained clearly (e.g. why push bad, spread operator good). I didn’t even know that objects could have spread operators, but makes a lot of sense.

    Some comments as I was running the code:

    1. I was having some issues with the paths specified. I used “./js/store/index” instead of “../js/store/index”.

    2. Was having an issue with exporting App to src/index.js so I deleted the `export default App` statement and did `export const App` at the top and imported { App } like so.

    3. Interestingly, using arrow functions to bind methods didn’t work. It may have something to do with babel presents specified. After googling a bit, it didn’t seem like best practice anyways for performance (oops, been writing React wrong!).

    Other comments:

    1. Would be great to see an article for redux-thunk and redux-saga, comparing the two.

    2. Would be great to learn about how to test Redux with React.

    3. Would be great to see a fullstack example with Node.

    Thank you so much for sharing your knowledge!

    1. Julia: thanks for your comment! It’s really rewarding to see other people learning from my tutorials.

      This Redux tutorial took me 1 week. It was written specifically for other fellow developers like you.

      I appreciate your suggestions! Stay tuned on this blog, maybe I’ll put something together about redux-thunk and redux-saga.

      Happy coding!

      1. Hi. Great little tutorial! Well done.
        My little App now follows your patterns. I have a few components/containers
        that use Redux/connect.

        The router doesn’t seem to want to play with connect(). Any ideas?

    2. On 3) Arrow functions in ES6 syntax make `this` refer to the lexical context and not the usual execution/invocation or the bound, context if it the case. Common mistake when starting on ES6.

      As a principle, as long as `this` is used, it is more cautious to stick to old fashion syntax, unless it is really what is expected, like some cases of self-invoking functions.

      Beside that, I really appreciated this tutorial.

  2. Thanks for the tutorial, it also worked well for an experienced developer new to redux

    A few tiny tweaks:
    * `Making our reducer complaint is easy.` <- Tiny typo, I think it should be “compliant"
    * .bablerc was already configured
    * I needed to run `npm install uuid`

  3. I avoided redux in my first app because it looked too complicated.
    When I did decide to learn it, I went from pole to post trying to find the right book, video, tutorial, article…you name it..anything that would help me grasp the concept (I am a seasoned developer) …but everyone trying to teach redux just seemed to get into very convoluted jargon, diagrams and explanations.
    I sat down with this page, your page, open and in one afternoon I am all set. I know redux (imagine Neo saying “I know kung fu!”)
    Thank you so much for a straight forward tutorial. Now I can go back and end expand my knowledge on the once-upon-a-time-complicated tutorials!

  4. Fantastic tutorial, Thank you Valentino.

    I just have doubt in this sentence that you said: “A pure function is one that returns the exact same output for the given input.”

    Is that the same term with side effects or it’s another principle of pure functions?

    1. Because as I noticed you are talking about immutability but the provided definition is not about side effects. That’s why I confused.

      Anyway, thank you for the amazing tutorial.

    2. Pedro, thanks for stopping by!

      A pure function is a function that:

      – returns the same output for the given input

      – has no side effects

      Those are two distinct principles, yet they are both about functional programming.

      Immutability is another functional programming concept and is strictly related to pure functions.

      So, yeah, they’re intertwined with each other as you can see!

  5. Outstanding article!!! cleared my major confusion with React/Redux which i was struggling for few weeks which is mapDispatchToProps usage in the container component.Now i will play with your repo to get better understanding.

  6. Thank you for this tutorial and all your other tutorials on react. I am an angular developer looking to explore more of reactjs and I find your tutorials very easy to follow as a react beginner. I was unsure on how to begin learning redux and this has given me a starting point.
    Please keep up the good work. cheers

  7. Hi, I think I am missing something, but I am getting a ‘module build failed’ error

    Module build failed: SyntaxError: Unexpected token (8:15)

    8 | return { …state, articles: […state.articles, action.payload] };

    for some reason it doesn’t like returning this object with state.

    Am i somehow missing babel or webpack, from the minimal template i downloaded from you?

    so far this is a wonderful tutorial!

  8. Hi disregard thelast comment, I missed the .babelrc

    however I am trying to follow your console redux part, and I amgetting this error wheni try and type the following:

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

    Error: Actions may not have an undefined “type” property. Have you misspelled a constant?

    why is this happening?

    1. Same error message here: “Actions may not have an undefined “type” property. Have you misspelled a constant?”

      Love the approach in explaining the seemingly mysterious concept, plain and simple, till I ran into the error message. How do you debug the problem?

  9. A small mistake: In the example of initial reducer that breaks the immutability
    return { …state, articles: state.articles.push(action.payload) };
    actually returns { articles: 1 } (the number of articles, not the array of article)

    So it probably should rephrase to (not really a good situation to use spread op here for the whole article, in my opinion)
    state.articles.push(action.payload)
    return state

  10. Great article! One of the simplest one on Redux I could find to get the concepts right.. Something I’m struggling to understand though in the reducer code, how exactly are we returning two values? (state,articles)? Is this some concept on functional programming?

    return { …state, articles: […state.articles, action.payload] };

  11. This is wonderful! mapStateToProps and mapDispatchToProps finally clicked after seeing them in two different components. Best explanation of react/redux I have read.

  12. Thanks a lot for putting this together and sharing it! It was very generous of you. Redux comes with a paradigm shift that can seem daunting at first but this tutorial really helps!

  13. Good tutorial, thanks for writing, I found it useful.

    If I can suggest one small improvement – it would be helpful if you explained why mapDispatchToProps is useful (so the component doesn’t have to know about redux / dispatch) and also what happens on the form submit. I got confused for a while thinking this.props.addArticle was the action creator in actions/index.js when in fact it comes from mapDispatchToProps.

  14. this is forever the best learning material I found for react – redux from all over the wide web.
    Thank you so much for such a masterpiece tutorial. would help me, if you have some reference for saga as well.

  15. Hey, this guide really helped me. Thanks for all your hard work.

    Wanted to let you know about one small typo. In the section: “React Redux tutorial: App component and Redux store”, there is a typo in the imports of the `./js/index.js`.

    should be:

    import store from “./store/index”;
    import App from “./components/App”;

    not:

    import store from “../js/store/index”;
    import App from “../js/components/App”;

  16. Hi Valentino and thanks so much for the tutorial.

    This may be a really dumb mistake, but I keep getting and error when I try to dispatch addArticle. Can’t figure out where exactly I am not importing it:

    store.dispatch( addArticle({ name: ‘React Redux Tutorial for Beginners’, id: 1 }) )
    VM13714:1 Uncaught TypeError: addArticle is not a function
    at :1:17

    Thanks again,
    Gal

    1. this is very embarrassing i am sorry. i forgot to save src/js/actions/index.js… 🙂

      please remove my comment and thanks again for the guide!!

  17. Very nice! I am an experienced developer but I started away from redux because of all the jargons. This was very simple. I can use redux now ?

  18. Very clear and well written tutorial! Impressive! I had no problem following the concepts or the code even though I have never used redux or react before.

  19. Thanks for your simple tutorial about React/Redux for beginners.
    I am a developer who is trying to learn react and redux and has problems while understanding tutorials from several websites.
    After reading your tutorial, it gets better to understanding the relationships between reducer,action and state.
    Also how to glue react and redux.
    Thanks very much.

  20. Thanks for this tutorial. It is so amazing, I have been confused about Redux until reading this. Thank you very much and wish you the best.

  21. You published an excellent guide for us. Even as React beginner I was capable to understand and reproduce all steps with the expected results.
    Thank you very much from Colombia.

  22. Joining the sentiment of the rest of people here:

    THANKS Valentino for taking the time to write and share this super comprehensive tutorial with a great simple (and very common) scenario.

    I now have a clearer idea of Redux and how it actually works.

    Grazzie mille!

  23. My bad, i use combineReducers and i forgot to add initialState. Please ignore my comment above. Thanks for nice tutorial.

  24. Excellent tutorial, thanks so much.
    Everything in your Redux and React tutorial worked great and your explanations are excellent.

    One minor issue I had was getting your bootstrap styles to work. I added

    // src/js/index.js
    import ‘bootstrap/dist/css/bootstrap.min.css’;

    Then:
    npm i bootstrap –save-dev

    That worked for me. Any other suggestions?

    thanks,
    David

  25. For some reason, I had this unjustified fear associated with learning redux. This tutorial is great and not a bit overwhelming. Thanks for taking the time to write this tutorial, Valentino!

  26. This article is really awesome. This is meant for those who just started with Redux. Even I had a lot of fear with Redux. But this article really simplifies everything.
    I read this article once and everything was kind of clear.But it will take some time for sure.
    I really appreciate you for this !!!! Good luck

  27. I was about to rip my hair off when trying to understand Redux. This tutorial gave me back the hope. Everything makes so much more sense now. Thank you sooooo much!!!

  28. Hi Valentino,

    Thanks for the super-simple intro to Redux!

    Some questions/suggestions:
    1. Why is immutability of state such a big deal (any benefits)? It will be good if you can touch upon this.
    2. It will be more helpful if you can begin with an example WITHOUT Redux, as a stateful React component, pointing out the issues in it and then show how Redux solves it. Can you modify this tutorial to such a format? (I am just pointing to the fact that learning is more effective when you start from the familiar and then move to the unfamiliar)

    Thanks again for the great tutorial!!

  29. By far the best tutorial on React Redux out there. I wish book authors can also read and get some tips.
    It is simple, clear and not confusing. I can appreciate the simplicity and the way all is explained. Kudos!

  30. Wow, that was super helpful. I’m learning redux for a new app I will build and was confused for days where to even start. This took me a big step forward on my journey to the store.

    I was a little confused about the placement of Files during the tutorial. The github-repo saved me at the end.

    Thanks from Berlin,
    bob

  31. Thank you so much for the tutorial. I feel like I have a handle on React and Redux separately, but was unsure about React-Redux bindings. Would love to see more tutorials, maybe with thunks??

  32. Well, as a React/Redux beginner, i haven’t yet read the entire article that I can already say it’s an excellent resource! Concise,detailed, very well written with pertinent examples, all I need to learn efficiently how to use Redux. Thanks a lot! I’d give you a beer for that awesome tutorial 😛

  33. Nice Article , Explained in easy to understand flow. I was able to follow each step without difficulty . I would sub title the Blog as Redux Simplified .
    Thanks a lot for the blog.

  34. Hi VALENTINO,

    First of all, Thank you for such a helpful tutorial.
    I am following all the instructions in the tutorial and creating my first React + Redux app. When I fired npm start. It is giving me following error in browser console.

    ERROR in ./src/js/reducers/index.js
    Module build failed: SyntaxError: Unexpected token (8:15)

    6 | switch (action.type) {
    7 | case ADD_ARTICLE:
    > 8 | return { …state, articles: […state.articles, action.payload] };
    | ^
    9 | default:
    10 | return state;
    11 | }

    Can you please guide me to make it work ?

    Thanks
    Harpreet Gill

  35. I am Using combineReducers and getting “Uncaught TypeError: Cannot convert undefined or null to object”. Without the combineReducer it is working fine. Below is snippet of my Reducers.

    article.js:
    import { ADD_ARTICLE } from “../actiontypes/action-types”;

    const initialState = {
    articles: []
    };

    const articleReducer = (state = initialState, action) => {

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

    export default articleReducer;

    reducers\index.js

    import { combineReducers } from ‘redux’;
    import articleReducer from ‘./article’;

    export default combineReducers({
    articles : articleReducer
    });

  36. Absolutely wonderful! The best free Redux beginner’s guide i have found accross the web !

    Thanks a lot my friend 🙂

  37. Thank you for the tutorial. I was looking at many sites to grab the concept of Redux, however had difficulties to understand.
    Your tutorial is really easy and flawless. I really appreciate your work.

  38. Thanks Valentino Gagliardi,
    I found this interesting and you really save my life from those four folders: Actions , reducers, store, and constants. i read poeples code but never understand the concept because i dont know how they are link together but now ,i can chase my dream. Thanks man.

      1. But in addition, i would like if you can do a write up on two entry in webpack , am currently working on personal project like that, my reason for doing this is to learn more,like react, webpack and others.
        In this project i have two entry, and the reasons for those entries are because,
        my home page as different dependecy from others e.g like my styling(css), but since the output are bundled and release on a single page and ,i need to load my dependency differently so it wont conflict one another.
        this is my webpack.common.js

        // import path from ‘path’
        const path = require(‘path’)

        module.exports = {
        devServer: {
        contentBase: ‘./client/dist’
        },
        output: {
        filename: ‘[name].bundle.js’,
        path: path.resolve(__dirname, ‘dist’),
        publicPath: ‘/’
        },
        watch: true,
        watchOptions: {
        poll: 1000,
        aggregateTimeout: 1000,
        ignored: /node_modules/
        },
        resolve: {
        extensions: [‘.jsx’, ‘.js’]
        },
        module: {
        rules: [
        {
        test: /\.s?css$/,
        use: [‘style-loader’, ‘css-loader’, ‘sass-loader’]
        },
        {
        test: /\.(png|gif|jpe?g|svg)$/i,
        use: [‘file-loader’]
        },
        {
        test: /.jsx?$/,
        enforce: ‘pre’,
        use: [
        {
        loader: ‘babel-loader’
        }
        ],
        include: path.join(__dirname, ‘/client’)
        },
        {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [‘file-loader’]
        }
        ]
        }
        }

        and my webpack.dev.js

        const merge = require(‘webpack-merge’)
        const path = require(‘path’)
        const webpack = require(‘webpack’)
        const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
        const CleanWebpackPlugin = require(‘clean-webpack-plugin’)
        const common = require(‘./webpack.common.js’)
        // to allow Dotenv files
        const Dotenv = require(‘dotenv-webpack’)

        module.exports = merge(common, {
        mode: ‘development’,
        entry: {
        app: ‘./src/index.js’,
        print: ‘./client/index.jsx’
        },
        devtool: ‘cheap-eval-source-map’,
        devServer: {
        contentBase: ‘./dist’
        },
        plugins: [
        new CleanWebpackPlugin([‘dist’]),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoEmitOnErrorsPlugin(),
        new Dotenv({
        path: ‘./.env’,
        safe: false
        }),
        new HtmlWebpackPlugin({
        template: ‘./client/index.html’,
        filename: ‘index.html’,
        inject: ‘body’
        })
        ],
        optimization: {
        splitChunks: {
        cacheGroups: {
        commons: {
        name: ‘commons’,
        chunks: ‘initial’,
        minChunks: 2,
        minSize: 0
        }
        }
        },
        occurrenceOrder: true // To keep filename consistent between different modes (for example building only)
        },
        stats: {
        colors: true
        },
        output: {
        filename: ‘[name].bundle.js’,
        path: path.resolve(__dirname, ‘dist’),
        publicPath: ‘/’
        }
        })

        So ,please how do i go about it, thanks in anticipation.

  39. This hit the mark. I was looking at a chapter in React book that introduced Redux, but the author went too quickly into Redux. Now I will be able to go back and understand the more advanced example presented.

  40. Thanks for posting this tutorial. As a beginner, I found it very easy to understand the redux concepts.. kudos!

  41. Hello
    first of all, thanks for this amazing and simple tutorial !! found it through reddit .
    i wanna talk about the issue i encountered in the section : React Redux tutorial: Redux store methods.

    i followed the instructions quite well, thing is the first two steps (subscribe and dispatch work well in the console and i see a result as per indicated here..but when i want to verify the store by getState() , the array is empty despite the action being dispatched already..
    what’s the matter?.
    Would love to shed light on this point.
    Thank you again for this amazing ressource !

  42. Hi.

    its really great really got a basic concept to make redux work.
    but i have little confusion.
    you setup window.store = store or you pass a single store in provider to app what if you have more than one store?

  43. Hello Valentino,
    Wonderful tutorial. Your tutorial got me up and running with redux with minimum effort. I wasn’t able to get hold of redux until I read this piece of GOLD from you. Thanks a lot.

    I have a question. You did not use some thing like:
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

    or,

    import { composeWithDevTools } from “redux-devtools-extension”;
    const sagaMiddleware = createSagaMiddleware();
    const store = createStore(
    rootReducer,
    composeWithDevTools(applyMiddleware(sagaMiddleware, thunk))
    );

    Then, how am I able to see redux changing states and other things in chrome redux extension ?

  44. Wouaw! So far this is the best tutorial I have found on react/redux for the beginners. It will require lot of practice to really get the differents concepts but everything is more clear in my head and seems simple now!
    Thank you very much!

  45. Great tutorial.
    I’ve looked through some of the guides to Redux but it still seemed very complex.
    Here topics are set very clearly and the way you put the knowledge in readers’ brains is amazing.
    Thank you very much.

  46. Thank you, Valentino!
    I’m really happy and touched when read this tutorial. Waited a long time to read one manual and awesome tutorial like this.

  47. Hi Valentino.

    Thank you so much for the tutorial. You really have made my life a lot better with this simple, easy to understand demonstration of how Redux works and how it plays with React. I cannot thank you enough!!

    Best regards,
    Ashvir

  48. Thanx a lot Valentino!
    It was my first time with Redux and I’ve found your tutorial very clear and well explained.

  49. Just amazing tutorial for react-redux. It is a real spoon feeding training I ever completed. It’s really helped me to brush up my react-redux knowledge. Thanks for this wonderful tutorial 😀

  50. I have found this React-Redux tutorial extremely useful, when i started with redux from the actual site, it sounded very complex but valentino has explained very well that it made me very easy and i learned in a day.
    Thanks valentino, for well stepped guide. Appreciate it !!!

  51. Thanks again! i rare post but this was such a great tutorial that wasn’t hello world but also wasn’t building a crazy web app either. Really straightforward and I could finally start to understand WHY we would use redux!

  52. Hi, Valentino. Let me tell you a little story.

    I had never had contact with React before. Until the company I work for decided to use it as our official front-end technology. So, I created a component from scratch managing the state the old way, with the setState method inside the component.

    Well, talking to some React enthusiasts, they told me I should take a look at Redux, for it had a better decentralized control of the state.

    So, I went to Google. I’ve read some articles, but yours is the best one ever. I mean, by far this is the best tutorial for React + Redux.

    Thanks so much for sharinh your knowledge.

    Best regards from Brazil.

    1. agreed. this is very to the point but not so rudimentary as hello world. I also REALLY appreciate that this is an original tutorial, and not something someone copied from somewhere and is a duplicate of other tutorials.

  53. Hi, Valentino,
    Thanks for the wonderful tutorial, i was struggling with the react redux from pas few months.
    but did not found any suitable tutorial.
    Thanks for making it simple. Now it is more clear.

    Thanks

  54. Thank’s very Much……….

    I was new to React, got My hands dirty with React and thought that’s all I need.
    Wait is that so?
    While working in My organization, came in front of REDUX, and was banging my head to learn REDUX, Nothing helped.
    But thank GOD, got this link.
    Now I can perform the Magic using REACT and REDUX…..

  55. Thanks Valentino! I’ve spent a lot of time (and money) trying to understand the principles you’ve just explained in this tutorial. Thanks a million!

  56. Wow! This article is amazing. I’m usually give up reading thing half way, but this article is simple and really easy to understand. Finally, I get to learn redux. Thank you so much.

  57. The only tutorial that actually helped me! I was about to give up attempting to understand how it works.
    Thanks A LOT!!! You’re awesome!

  58. OMG, thank you so much for such a simple tutorial, I’ve been struggling to pick up Redux for ages till I saw this. You’re awesome~!!!

  59. Awesome article! I’ve been trying to understand Redux for my job, and this hands-down the best tutorial I’ve come across! You really do a great job of walking the reader through, and I now have my first reducer working.

  60. That’s awesome and pretty straightforward. The example that you have provided is very easy to understand the difference between react, redux and how to connect between them. GREAT WORK! much appreciated!

  61. After several books on React / Redux left me confused and frustrated your tutorial gave me a flicker of light!! Great job. I don’t fully have a grasp on the functional programming aspects of Redux but this tutorial does a fantastic job of guiding developers through the Redux maze. Again cudos!

  62. Thank you for this post. Before I read this, I thought I’d grasped the principle of using React and Redux together but I just couldn’t seem to join all the bits together. In particular I didn’t understand how to implement the reducers, mapStateToProps and mapDispatchToProps. But now, thanks to this post and Matt Stow’s post on Redux and Thunk, my first component is working at last.

    The one thing I struggled with was the “state” parameter being passed to the reducers. After adding lots of console.log calls all over my code, it seems that this is actually a property of the overall Redux state, the property with the same name as the reducer function – is this the case? If so then it may help future readers if you point this out.

    And a question, if I may. As I’m using create-react-app, and so can use ES6 syntax, I’ve implemented my action creators as static methods within a class rather than as functions. This is mostly because I work with C# a lot and so it feels more natural to me to put my code in classes where possible, but also because I only need to export/import the class rather than every action creator. For example:

    export default class CollectionSelectorActions {
    static actionTypes = {
    isLoading: ‘COLLECTION_SELECTOR_MODEL_IS_LOADING’,
    succeeded: ‘COLLECTION_SELECTOR_MODEL_FETCH_DATA_SUCCESS’,
    hasErrored: ‘COLLECTION_SELECTOR_MODEL_HAS_ERRORED’,
    collectionSelected: ‘COLLECTION_SELECTOR_COLLECTION_SELECTED’,
    }

    static fetchData(url) {
    // …
    }

    static isLoading(isLoading) {
    // …
    }

    static succeeded(model) {
    // …
    }

    static hasErrored(hasErrored) {
    // …
    }

    static collectionSelected(selectedCollection) {
    // …
    }
    }

    But none of the Redux examples I’ve seen on the www seem to do this. Is this approach likely to cause me problems as my app grows?

    Thanks again.

    1. Hi Simon, exactly, “state” is the argument you give to the root reducer. In Redux the state is a product coming from the root reducer (or from the reducers if there are many). Regarding your question, I don’t see any problem with your code though it steers away from idiomatic Redux.

  63. Well constructed way of presentation. Even I am new to Redux I can able to understand things easily due to way you carried… and could you please share the full source as a zip, because I followed and implemented all the code but I see nothing display in the url http://localhost:8080/
    Could be better if one step ahead from project creation…

  64. Hi, I get “Target container is not a DOM element.” error in

    src/js/index.js

    3 | import { Provider } from “react-redux”;
    4 | import store from “./store/index”;
    5 | import App from “./components/App”;
    > 6 | render(
    7 |
    8 |
    9 | ,

    Had anyone some idea what this might be, please?
    Thanks
    Tom

  65. Note that I used create-react-app but in the html the div is called ‘root’
    So if you get the “Target container is not a DOM element” error, go to src/js/index.js and change “document.getElementById(“app”)” to “document.getElementById(“root”)”

    Otherwise, this was a really good tutorial. I had worked with react-redux apps started by other people before, but whenever I came across errors I knew the solution, but not the CAUSE (for example, the part where you map dispatch and need null)

  66. Your .babelrc file configuration is incorrect:

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

    It should be:

    {
    “presets”: [“@babel/preset-env”, “@babel/preset-react”],
    “plugins”: [“transform-object-rest-spread”]
    }

  67. Great tutorial. Didn’t finished yet.

    I noticed a small error.

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

    should be
    store.dispatch( addArticle({ title: ‘React Redux Tutorial for Beginners’, id: 1 }) )

  68. Really great tutorial. Helped me a lot. Simple and short.

    But you a have a little mistake here:
    {
    type: ‘ADD_ARTICLE’,
    payload: { name: ‘React Redux Tutorial’, id: 1 }
    }
    And here
    store.dispatch( addArticle({ name: ‘React Redux Tutorial for Beginners’, id: 1 }) )

    Should be:
    {
    type: ‘ADD_ARTICLE’,
    payload: { title: ‘React Redux Tutorial’, id: 1 }
    }
    And here:
    store.dispatch( addArticle({ title: ‘React Redux Tutorial for Beginners’, id: 1 }) )

    And I have a question. I didn’t understood the need of the file src/js/index.js. I removed it from my test application and it is working fine. What am I missing? Which is the purpose of this content?

    import store from “../js/store/index”;
    import { addArticle } from “../js/actions/index”;
    window.store = store;
    window.addArticle = addArticle;

  69. Sorry for the spamming. No confirmation message so I wasn’t sure if it was posted. Please disregard previous two.

    Really great tutorial. Helped me a lot. Simple and short.

    Saw that you corrected the error I mentioned, but you still have a little mistake here:
    {
    type: ‘ADD_ARTICLE’,
    payload: { name: ‘React Redux Tutorial’, id: 1 }
    }

    Should be:
    {
    type: ‘ADD_ARTICLE’,
    payload: { title: ‘React Redux Tutorial’, id: 1 }
    }

    And I have a question. I didn’t understood the need of the file src/js/index.js. I removed it from my test application and it is working fine. What am I missing? Which is the purpose of this content?

    import store from “../js/store/index”;
    import { addArticle } from “../js/actions/index”;
    window.store = store;
    window.addArticle = addArticle;

    1. In fact, what I was doing was importing store and actions directly in my index.js file :
      import store from ‘./js/store’
      import { addArticle } from ‘./js/actions’

      But if i replace it by
      import ‘./js/index’
      which contains the imports and adds them to the window object

      import store from “../js/store/index”;
      import { addArticle } from “../js/actions/index”;
      window.store = store;
      window.addArticle = addArticle;

      I must call
      window.store.subscribe(() => console.log(‘Dispatch called!!!’))
      console.log(window.store.getState())
      window.store.dispatch(window.addArticle({ title: ‘React Redux Tutorial for Beginners’, id: 1 }))

      Instead of
      store.subscribe(() => console.log(‘Dispatch called!!!’))
      console.log(store.getState())
      store.dispatch(addArticle({ title: ‘React Redux Tutorial for Beginners’, id: 1 }))

      There is no other way? Seems too verbose…

  70. Thanks for the great article. What if you actually DO need to change the state? In my case I need to access a currentNodeId in components that do not have a parent child relationship. I see there’s a higher order reducer pattern. Maybe that is my answer?

  71. This has really given me a solid base to understanding Redux.
    It is the best free guide I read for a long time on any of the latest skills we need as developers.
    Thanks again!

  72. Hello,

    thank you for the tutorial.
    But for me it was time wasting.
    You do not explain your react envirenment. I created one with create-react-app test.
    I do not have the .babelrc config file, i get 3 errors i am not able to fix.
    1.:
    Could not find “store” in the context of “Connect(ConnectedList)”. Either wrap the root component in a , or pass a custom React context provider to and the corresponding React context consumer to Connect(ConnectedList) in connect options.
    2.:
    Could not find “store” in the context of “Connect(ConnectedForm)”. Either wrap the root component in a , or pass a custom React context provider to and the corresponding React context consumer to Connect(ConnectedForm) in connect options.
    3.:
    Could not find “store” in the context of “Connect(ConnectedList)”. Either wrap the root component in a , or pass a custom React context provider to and the corresponding React context consumer to Connect(ConnectedList) in connect options.

  73. Very well done for a somewhat beginner. I’ve been struggling with the redux docs, and other tutorials, they seem to all be written for React experts. This was much more helpful, explained the little details better that most others gloss over or ignore. I’ll check out some of your other blogs in the future.

  74. I followed it all and copy pasted everything exapt that I changed “document.getElementById(“app”)” to “document.getElementById(‘root’)” as suggested here for create react app ,but the messages doesn’t appear on the list in the left ! 🙁

  75. I implemented the code but the messages doesn’t appear in the list unless I change some class name tag for example, let it render and change the name back.. Only then the new message appears..

    It’s like the app doesn’t render the list in real time. Did you make changes to the code maybe ?.
    Can you verify if your version works and if it matches the code in the guide ?

  76. This is a brilliant tutorial, extremely helpful.. Thanks.

    Feedback on blog site: Only the comment part on this blog page is so large that I had to scroll down a lot to write a comment

  77. This tutorial is proving extremely helpful for learning Redux.
    I am done only with the Console program explained early in the tutorial, it’s allowing me to explore the basic Redux concepts (Action, Reducer, dispatch, getState()) etc. in the browser console itself.
    Thanks again for such a wonderful Explanation!

  78. The best Redux tutorial on the web by far. Understood every bit of it. This makes the actual Redux documentation much easier to understand.

    For anyone reading this, I suggest you read the actual Redux documentation alongside this guide as it will really allow you to understand all the features available when using React with Redux.

  79. Really,It’s very useful. Before, reading of your tutorial it was scary to use redux. But, now after getting clear concept of redux it’s easy to use.
    Thank you.

  80. Connect, MiddleWare, Custom MiddleWare, Props , State, actions, Action Creators, mapStateToProps, rootReducer, reducer, dispatcher, thunk ……

    Is that everything we need to know when dealing with state?
    Is it possible that it would be easier to do app development without using a framework at all?

    Wtf….

  81. Loving the tutorial so far, I have had contact with React/Redux a year ago on an internship but since I never practiced afterwards I forgot the majority of it and that’s why I decided to learn it again and found your tutorial. I am literally following the tutorial line by line and facing an error on the “Redux store methods” part. It gives me this error when I try to do store.getState() :

    throw new Error(‘You may not call store.getState() while the reducer is executing. ‘ + ‘The reducer has already received the state as an argument. ‘ + ‘Pass it down from the top reducer instead of reading it from the store.’);

    If you (or anyone) could help it would be great. If any print screens are necessary just let me know.

    Cheers from Portugal!

  82. typo in “Worth nothing”, should be “worth noting” right? I had a hard time understanding that sentence because of this:), I bet no native speaker would notice it but as a EASL guy that’s an omg moment. and Thanks for the tutorial, nicely done. One just like this one with typescript is needed for the people of the world 😉

  83. Very nice tutorial!
    I have am now working with react/redux project. and I had some issues that I couldn’t understand.
    So I came here to read this redux tutorial.
    And now I finally understand the flow of redux architecture and I have the confidence to do it on my own.
    Thanks for your effort for making this one!

    PS: One day, I also want to make such kind of tutorials for other guys like me.

  84. Excellent tutorial! Although no diagrams, the wordings and the use of bold along with sample codes make it easy to follow.
    It really helped me learn React and Redux, thank you Valentino!

    Upon trying saga, I got this error “regeneratorRuntime is not defined”. I fixed it by adding this line on top of sagas/api-saga.js:
    import “regenerator-runtime/runtime”;

  85. Thanks, Valentino! That was extremely handy and 100% understandable.

    Working on Angular’s (4~7) REDUX (@ngrx), for over 1 year, this is my first REDUX apply to a React App.
    I took the liberty to try it out right from React CLI to the last Saga part and it rools ike a Rolls! Thank you!

  86. i love this post, i would like to give you thanks because was severus days that i was searching how to learn redux. nice job. only a stuff more , i had a trouble that said “regeneratorRuntime is not defined” i could resolve resolve it using the next code at the first the file store/index.js
    import ‘regenerator-runtime/runtime’;

  87. Hi Valentino Gagliardi!

    Thanks for writing this article. It is really amazing and interesting the way you explain. Just one request can you please make a similar article for server-side rendering?

  88. Thank you for this complete and well explained tutorial. I had a problem with webpack and babel using generator functions, but I could solve it with polyfill.

  89. Your tutorial has been one of the best I have seen since I started learning react. Very explanatory and easy to understand. Thank you for this amazing resource!

  90. Honestly, this is one of the best tutorials I’ve ever seen! I spent three hours of intense work completing it—making sure I understood every line—and now React and Redux just make sense. I speak a little Italian, but not enough to attempt reading “Piccolo Javascript.” Will it be translated in English?

  91. One of the best guide on Redux for beginners. I basically read it two times. For the first time, I just read and understood the concepts. The second time, I implemented it in my project. Kudos for the outstanding work.

  92. Fantastic tutorial, you should add a buy me a coffee link :), I think you’d have some takers….

    I’m fortunate in that I’m trying to understand this redux/react stuff from some well written source code in the company. They’ve opted to use it with typescript, and for the actions they are using a library typesafe-actions importing createAction.

    a sample action export looks like:

    export const expand = createAction(‘chopper/EXPAND’,
    resolve => (aID: string) => resolve(aID));

    From what I can tell, this looks to be a way I prefer to the 2 options above, it may be worth exploring further. Also typescript looks too improve code maintanability & readability, it may be worth exploring it in a separate article.

    Fantastic article, I will be forwarding it around the office.

  93. Thanks a lot for this tutorial!

    You’ve made learning Redux really, really easy (at comparison to their docs, that could be overwhelming for most people).

    However, one question arose me, when attempted to start using the knowledge on my own.
    How would you implement Redux-saga with RealmJS Database?

    By the way Realm works you need to create an asynchronous promise forcibly inside your React Component. Thus it cannot be on the api-saga.js, neither as an independent function.

    For how I see it, using redux-thunk would probably be the best idea on this particular case, but I believe I’m probably missing something here.

    1. Just resolved it. Were able to make it work with both redux-thunk and redux-saga.

      My mistake was that it is indeed posible to use Realm outside React, as long as it’s JS. I was confusing React components with JavaScript functionality, and thought that Realm wouldn’t be able to work outside of it.

      Sorry for any incovenience.

      Thanks again for this extraordinary tutorial!, I really thank you a lot.

  94. Hi,
    I am Fresher and new in UI development. I have started with learning javascript. Worked on different frameworks like JQuery, React, Ember and basic of React-Redux but all things are in basic levels.
    Thanks for such a great and helpful experience of learning redux concepts in a much better way.
    It is so much easy to understand and get difficult things in more understandable words.

    Thank you 🙂

  95. Thank you for this tutorial! Many concepts still confuse me, especially starting on the part where redux-thunk came into the picture. I will review this article again at some other time.

    I have a question though. After running `npm i redux-saga –save-dev`, it seems that redux-thunk went missing in my node_modules right after. As a result, before I changed `/src/index.js` (I used create-react-app) to import from redux-saga, the application gave an error that it could not find redux-thunk. Is this normal?

    One last suggestion that I have is it could be helpful to highlight which lines of code you changed! I am the kind to follow along and code it by myself instead of copy-pasting. Many a time I found myself accidentally skipping over a line that you added but I had not noticed.

    All in all, a great introductory guide! Thanks once again and cheers 🙂

  96. Thank you Valentino, this is the most simple and straight forward tutorial i have seen on this topic so far. In fact I have had sleepless nights trying to wrap my head around react-redux implementation until I saw your tutorial. It was as easy as I can get.

    Thank you so much.
    I also enjoyed your tutorial on web pack 4. Bravo!!!

  97. Great job! Easy tutorial to follow along and just what I needed for a redux intro. Somewhat similar to MVC coming from a laravel world. Thanks for posting the github full code link.

  98. Great job Valentino.
    Thank you to write this easy and cool tutorial.
    You authorize me to translate to portuguese, post in github with a link to the original tutorial?

  99. This was very good for me. My seniors already wrote the code. but i can’t understand. I’m understanding now. thank you.

  100. I have been trying to work with redux/redux-thunk/redux-sagas on and off for a couple of years. I finally understand how it can all work together! It is people like Valentino taking the time to honestly write his experience in understanding the technology that keeps me moving forward…

  101. Hi Valentino,
    Thank you very much.
    Now I have complete understand about React Redux. I have never seen anywhere like this explanation. Each and every steps with example is very clean and easy understandable. Once again I thank you.

  102. Valentino

    The complete guide, laid out in an easy (relatively speaking) to understand manner, and you went all the way to explain commonly used Redux related libraries. Kudos!

    Thank you for advancing my knowledge. I badly needed this tutorial.

    Regards
    Tony

  103. I would like say thanks! Excellent write! You, sir, turn a complex subject into a simple recipe. Continue with the very, very good job!

  104. This tutorial is both short and comprehensive (it reaches all key aspects of Redux and React-Redux). An excellent “quick start guide”. The best I’ve found so far..

  105. thank you so much, i was hopeless to learn redux.
    im still laughing to: “I know, you want to cry and change career but bear with me.”i so relate but its too late for me lol.

  106. THANK YOU VERY MUCH.
    i have a question i appreciate if any one knows the answer.
    what these three lines do in handleSubmit function:

    const id = uuidv1();
    this.props.addArticle({ title, id });
    this.setState({ title: “” });

  107. Hi Valentino! Great article it clear me a lot. I’ve got one question. On form.js on line
    const Form = connect (null, mapDispatchToProps)(ConnectedForm);
    I get this error:
    Parsing error: Identifier ‘Form’ has already been declared

  108. This was a very very helpful blog, thanks for sharing your findings, It really help me out to understand this bunch of technologies that at first looks so scary

  109. Hey Valentino,

    Thanks for your tutorial, it’s great for redux understanding.

    I’ve a question, Imagine you ant do delete an article in the List.jsx, should you do?:

    function handleDelete(event,articleId) {
    event.preventDefault();
    const id = articleId;
    removeArticle({id});
    }

    const ConnectedList = ({ articles }) => (

    {articles.map(el => (

    {el.title}
     
    {
    handleDelete(e, el.id)
    }} className=”btn btn-danger btn-lg”>
    DELETE

    ))}

    );

  110. Very helpful, first time i understood Redux and well written too. Lot of AHA moments too. Happy to check more your blogs!
    .. I would only add some drawing / diagram for how its all connected (action, store, reducer, middleware)

  111. Hi.
    I have a problem in the part ‘React Redux tutorial: asynchronous actions in Redux with Redux Thunk’.
    I copy the component Post and modify the file index in actions but when I launch the application, there is an error.
    The console report is ‘TypeError: this.props.getData is not a function’.
    I don’t know why it doesn’t find the getData function created in the actions ?
    Does somebody have a idea ?

      1. Yes I add the line ‘ export default connect(mapStateToProps, { getData })(Post); ‘ at the end of the component Post.
        But I steel have the same error.

  112. wow I am so grateful to have found this… I have tried to learn redux on and off for months and no matter how many tutorials I went through I just could not “get it”. This post seriously changed my entire perspective, I had so many a-ha! moments that finally clarified all the concepts that I thought I was too dumb to understand. Thank you thank you thank you!!! Anyway I feel like people don’t get acknowledged enough for their help and I will be looking out for your posts.
    TLDR; you had a serious positive impact on someone’s life today 🙂 and keep doin what you’re doin

  113. Nice tutorial, thanks.

    But I can’t figure out how to display a message if we submit a forbidden word? As for now, nothing happens and it would be great to notify users in such cases.

    Probably I poorly understood the subject if I can’t solve this case….

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.