Redux for Beginners – Learn Redux with Code Examples
Tags: javascript, react, codenewbie
Published: 2021-05-19 06:12:27

Redux can be confusing for beginner React developers to understand. There are a lot of concepts you need to know to use it properly, like reducers, actions, store, pure functions, immutability, and much more.

But every React developer should know the basics of how to work with Redux since industry projects often use Redux to manage larger projects.

So in this article, we'll explore the basics of Redux and how to use it.

**Here's a preview of the app which we'll be building in the [Mastering Redux](https://master-redux.yogeshchavan.dev/) course.It's a great project you can add to your portfolio and resume.**

**Today is the last day to get the course at discounted price.**

Note that, in this app, I have used INR as the currency for displaying the prices but you can easily change it to USD or AUD or any other currency with a single configuration change in the app.

{% youtube 2zaPDfCKAvM %}

## What Is Redux?

Redux is a state management library that helps to better manage state in the application.

Redux library is not specific to React. It's a library that you can use in any other library or framework like Angular, Vue and even vanilla JavaScript.

But Redux is mostly used when working with React.

Redux provides a single store that we can use to manage a large amount of data.

## How to Get Started with Redux

Let's create a new React project to learn Redux basics.

Execute the following command in the terminal/command prompt to create a new React project using create-react-app:

```js
npx create-react-app redux-demo
```

> `npx` in this case allows us to use the `create-react-app` npm package to create a new React project without installing it on our local machine.

Once the project is created delete all the files from the `src` folder and create a new file `index.js` inside the `src` folder.

Now open the terminal again and execute the following command from the `redux-demo` folder:

```js
npm install redux@4.1.0
```

The above command will install the redux library with version `4.1.0` to use in our project which is the latest version at the time of writing this article.

## How to Create the Redux Store

In Redux, the store is used to manage and track the changing data in the application. 

To create a store we need to import the `createStore` function like this:

```js
import { createStore } from 'redux';
```

The `createStore` function accepts three arguments:

* the first argument is a function that is normally known as a reducer (required)
* the second argument is the initial value of the state (optional)
* the third argument is an enhancer where we can pass middleware If any (optional)

> You will see how to create your own middleware as well as use the already available middleware libraries in the course.

Take a look at the below code:

```js
import { createStore } from 'redux';

const reducer = (state, action) => {
  console.log('reducer called');
  return state;
};

const store = createStore(reducer, 0);
```

Here, we've first defined a reducer function using ES6 arrow function syntax. You can use the normal function instead of the arrow function If you want.

Inside the reducer function, we're logging some text to the console and then returning the value of the state from the function.

Then we pass that reducer function to the `createStore` function as the first argument and `0` as the initial value of the state as the second argument.

The `createStore` function returns a store that we can use to manage the application data.

The reducer function receives state and action as the parameters.

The initial value of the state which we passed as `0` for the `createStore` function is automatically passed as the value of the `state` parameter.

But it's a much more common practice to initialize the state inside the reducer itself rather than passing it as a second argument to the `createStore` function like this:

```js
import { createStore } from 'redux';

const reducer = (state = 0, action) => {
  console.log('reducer called');
  return state;
};

const store = createStore(reducer);
```

Here, we're using ES6 default parameter syntax for initializing the state parameter to value `0`.

Once the store is created, we can use the `subscribe` method provided by the store to subscribe to the changes in the store as shown below:

```js
store.subscribe(() => {
  console.log('current state', store.getState());
});
```

Here, using the `subscribe` function, we're registering a callback function that will be called once the store is changed.

And inside the callback function, we're calling the `store.getState` method to get the current value of the state.

Now, open the `src/index.js` file and add the following contents inside it:

```js
import { createStore } from 'redux';

const reducer = (state = 0, action) => {
  console.log('reducer called');
  return state;
};

const store = createStore(reducer);

store.subscribe(() => {
  console.log('current state', store.getState());
});
```

Now, If you run the application by executing the `npm start` command from the terminal and access [http://localhost:3000/](http://localhost:3000/),  you will see the `reducer called` message printed in the console.

![reducer_log.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1621391651358/qoB6XXwU7.png)

This is because the reducer gets called immediately once we pass it to the `createStore` function.

## How to Change the Store

Now, we're done with creating the store. But the store is not much of use right now. Because the store is connected using the reducer function but we have not added any code inside the reducer to manage the store. So let's do that.

**The only way to change the store is by dispatching actions.**

An action is an object sent to the store like this:

```js
store.dispatch({
  type: 'INCREMENT'
})
```

Here, we're calling the dispatch function available on the `store` to send an action with the type `INCREMENT` to the store.

The dispatch function takes an object as a parameter which is known as action.

The action must have a `type` property as shown above. If you don't pass the `type` property then you will get an error.

> It's a common practice and recommended to specify the `type` value in uppercase.

The type can be any operation you want to perform like `ADD_USER`, `DELETE_RECORD`, `GET_USERS` and so on.

If you've multiple words you can separate them with underscores like this `{ type: 'INCREMENT_NUMBER' }`.

Now, open the `index.js` file and replace its contents with the following code:

```js
import { createStore } from 'redux';

const reducer = (state = 0, action) => {
  if (action.type === 'INCREMENT') {
    return state + 1;
  } else if (action.type === 'DECREMENT') {
    return state - 1;
  }

  return state;
};

const store = createStore(reducer);

store.subscribe(() => {
  console.log('current state', store.getState());
});

store.dispatch({
  type: 'INCREMENT'
});

store.dispatch({
  type: 'INCREMENT'
});

store.dispatch({
  type: 'DECREMENT'
});
```

Now, If you run the application by executing the `npm start` command from the terminal, you will see the following logs printed in the console.

![changing_store.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1621391663932/da5lc7uLm.png)

As you can see for every action dispatched to the store, the store gets changed and so we're able to see the different values of the state in the console.

In the above code, our reducer function looks like this:

```js
const reducer = (state = 0, action) => {
  if (action.type === 'INCREMENT') {
    return state + 1;
  } else if (action.type === 'DECREMENT') {
    return state - 1;
  }

  return state;
};
```

Whenever we call the `store.dispatch` function, the reducer function will be called and whatever returned from the reducer will become the new value of the store.

So when the first time we dispatch an action to the store like this:

```js
store.dispatch({
  type: 'INCREMENT'
});
```

the first If condition inside the reducer function will be executed that will increment the `state` value to `1` which was initially initialized to `0` using ES6 default parameter syntax and it will be returned from the reducer function.

**Note that we're using the value of the `state` to calculate the new value and we're not modifying the original `state` value like this:**

```js
if (action.type === 'INCREMENT') {
   state = state + 1;
   return state;
} 
```

So the above code is wrong because in reducer we should not modify the original state. Doing so will create issues in your application and is not recommended.

> You will learn why we don't directly change the state and various ways of creating copies of array and object in detail in the course.

And because we've added `store.subscribe` function in the `index.js` file, we're getting notified about the changing store as we can see the logs in the console.

So when we again call the dispatch with type `INCREMENT`, the first If condition will be executed again so 1 will be added to the previous state value which was 1 and the final state value will become 2.

Then we're dispatching the `DECREMENT` action to the store like this:

```js
store.dispatch({
  type: 'DECREMENT'
});
```
 
which will execute the else condition inside the reducer and it will decrement the state value by 1 so 2 - 1  will become 1.

Note that, inside the reducer, we're also returning state at the end so If none of the condition matches, the default previous state will be returned from the function.

It's a common practice to use a switch statement inside the reducer instead of the if-else condition like this:

```js
const reducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
};
```

In addition to the type, we can also pass extra information as a part of the action.

Replace the contents of the `index.js` file with the following code:

```js
import { createStore } from 'redux';

const reducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + action.payload;
    case 'DECREMENT':
      return state - action.payload;
    default:
      return state;
  }
};

const store = createStore(reducer);

store.subscribe(() => {
  console.log('current state', store.getState());
});

store.dispatch({
  type: 'INCREMENT',
  payload: 1
});

store.dispatch({
  type: 'INCREMENT',
  payload: 5
});

store.dispatch({
  type: 'DECREMENT',
  payload: 2
});
```

Now, If you run the application by executing the `npm start` command from the terminal, you will see the following logs printed in the console.

![with_payload.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1621391678225/I_x5S5SMK.png)

Here, while dispatching an action to the store, we're passing a `payload` with some value which we're using inside the reducer to increment or decrement the store value. 

Here, we've used `payload` as a property name but you can name it whatever you want.

Our reducer function looks like this now:

```js
const reducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + action.payload;
    case 'DECREMENT':
      return state - action.payload;
    default:
      return state;
  }
};
```

So when we dispatch actions with type `INCREMENT` like this:

```js
store.dispatch({
  type: 'INCREMENT',
  payload: 1
});

store.dispatch({
  type: 'INCREMENT',
  payload: 5
});
```

the following code from the reducer will be executed

```js
return state + action.payload;
```

which will first add 1 and then 5 to the previous value of the state so we go from 1 to 6 and because of the `DECREMENT` action type

```js
store.dispatch({
  type: 'DECREMENT',
  payload: 2
});
```

we go from 6 to 4 so the final value of the store will become 4.

Here's a [Code Sandbox Demo](https://codesandbox.io/s/goofy-hooks-y1w9s?file=/src/index.js).

### Thanks for reading!

This was a quick introduction to Redux from my [Mastering Redux](https://master-redux.yogeshchavan.dev/) course.

In the Mastering Redux course, you will learn:

* Basic and advanced Redux
* How to manage the complex state of array and objects
* How to use multiple reducers to manage complex redux state
* How to debug Redux application
* How to use Redux in React using react-redux library to make your app reactive.
* How to use redux-thunk library to handle async API calls and much more

and then finally we'll build a complete [food ordering app](https://www.youtube.com/watch?v=izSw74H08Bc) from scratch with stripe integration for accepting payments and deploy it to the production.

**Today is the last day to get the [Mastering Redux](https://master-redux.yogeshchavan.dev/) course at discounted price**.

**So click the below image to get the course at just $12 instead of the original price of $19.**

**You will also get a free copy of my popular [Mastering Modern JavaScript](https://modernjavascript.yogeshchavan.dev/) book If you purchase the course till 19th May 2021.**

[<img src="https://gist.github.com/myogeshchavan97/98ae4f4ead57fde8d47fcf7641220b72/raw/c3e4265df4396d639a7938a83bffd570130483b1/banner.jpg">](https://bit.ly/3w0DGum)

**Want to stay up to date with regular content regarding JavaScript, React, Node.js? [Follow me on LinkedIn](https://www.linkedin.com/in/yogesh-chavan97/).**

[<img src="https://cdn.buymeacoffee.com/buttons/default-yellow.png" >](https://www.buymeacoffee.com/myogeshchavan97)