Redux explained from a beginner's perspective (simplified)
Tags: javascript, beginners, redux, react
Published: 2022-05-20 12:27:19

Redux is one of the tools that can be challenging for a beginner to get started using it. from its fancy terms like `reducers,` `dispatch`, `payload`, to a lot of packages built on top of it like `Redux-saga`, `Redux-thunk`, `Redux-promise`... one may struggle even to find where to start and easily get lost into these Redux Mumbo jumbos. 
In this guide, we will go through the basics of Redux from a beginner's perspective using the simple plain English language. By the end of the article, you will have a strong understanding of Redux basics, and we will use our new Redux knowledge to build a  simple banking application.

**Note**: This article will use the traditional way of using Redux (without using `redux-toolkit`). I intentionally made it this way to focus on explaining redux concepts with less confusing code.
I plan to make this a series and in the following articles, we will integrate redux-toolkit in our code and see precisely the problems that the `redux-toolkit` was created to solve. 
Don't worry if you don't even know what `redux` or `redux-toolkit` we will cover everything from scratch

**Prerequisites**
- We will be building everything from scratch; you only need VS code and node installed on your machine 

Let's start by explaining some of the Redux terminologies
**1. What exactly is Redux**
When you visit the official Redux [Website](https://redux.js.org/), you see this simple definition ==> Redux: 

> _A Predictable State Container for JS Apps_ 

But what does this even mean? How did they manage to make 7 words so difficult to understand?

**First, what is the application state?**
Generally, the state of your application is the situation or environment in which your app is running, and this state usually changes. For example, suppose you have a website like Facebook where users can log in and log out from their accounts, 
when someone just lands on the website, we can say that the application is in a state where no user is logged in, but as soon as they enter their credentials and click the login button, the state changes, and now the app is the state where someone is logged in. 
 
Not clear yet? Let's take another example, let's say on a website users can visit and decide to use the dark or light mode by toggling the theme slider. As soon as they switch modes everything will change in the app and the selected mode will be applied.
We can say that the app was in the state of light mode and is now in the state of dark mode.
      
As explained in the above examples our application behaves differently according to the current state and we need to track the state of the application to build modern information like is the user logged in?, is the page loading?, the key that the user pressed... 
That's where `Redux` comes into the picture as a container of application state.

Basically in Redux, the state of our application is just a long JavaScript object containing all the information describing every change we need to keep track of.

For example, It can look like the following (note that the examples are simplified for the sake of clarity

```js
let state = {
  userLoggedIn: true,
  mode: "dark",
}
```
We can describe the above state by saying that the user is logged in and chose to use dark mode. When using Redux this object will be managed by Redux and it will track all changes we can access the updates from Redux whenever we want.

Back to the Redux definition 

> so the definition that Redux is "A Predictable State Container for JS Apps" means that Redux is so good at managing your application state that whenever the state in your JS application expects that it is recorded by Redux

Now that we have covered the Redux definition let's take a look at some of its concepts 

**2. Redux actions**
Redux's actions are much similar to real-life actions, they describe how to do something. like the way, you can have an action of _Reading a book_ that's the same with Redux, except that in Redux we are dealing with the application state. 

As we saw that we constantly need to change our application state according to different conditions, we need a way to tell Redux how to change the state, and that's where we use actions.

In Redux, **an action is a simple JavaScript object that explains the action to perform on our state in order to manipulate it**. 

for example, an action can look like this 

```js
const action1 = {
type: "DO_SOMETHING"
}
```

- Redux actions will always have a property of `type` which describes what to do. and this property is **compulsory**. Note that by convention actions type is written in capital letters separated by underscores (also known as capital snake casing) 
- Redux action can optionally have a property called `payload` which can be anything that gives more detail about how to do the action but this field is optional.

Let's explain Redux actions more using an example. Let's say in real life you want to go to "Simba supermarket" to buy "10 red apples", we can describe this as a Redux action like the Following

```js
const action = {
  type: 'BUY_APPLES',
  payload: {
    shop: 'Simba supermarket',
    type: 'red',
    number: 10,
  }
};

```
In this example, our action is just an object containing the type describing what we want (to buy apples) and in our case, the payload is another object containing additional information about where to buy apples which type, and how much to buy.

For a more practical example let's say we have a ToDo app and in the app, we have a state of all TODOS, you would want to create an action that will add a new TODO to the state and the action could be like the following

```js
const action = {
type: "ADD_TODO",
payload: "Walk the dog" // payload contains the actual task to do
}
```
- Note how the payload can also be just a string as in the current I don't have additional information to explain this action 

**Redux action creators**
In Redux as the name says `action creators` **are functions that create actions**. But we already created action in the previous why would we need to use action creators? 

Generally, we use functions when we don't want to repeat the same code over again. In the above buying apples example what if we wanted to buy 7 green apples from a different shop? The action is still the same (buying apple) therefore we don't need to create brand new action we can just use a function that takes input and return appropriate action and can be reused whenever needed.

We can use something like

```js
const createAction = (shopName, appleType, appleNumber) => {
  return {
    type: 'BUY_APPLES',
    payload: {
      shop: shopName,
      type: appleType,
      number: appleNumber,
    },
  };
};
```
Action creators are functions that just return the action object and they can be given different arguments to provide new actions dynamically

**3. Redux Reducers** 
So we now have the stat, and we have an action we want to do to change the state how exactly do we tell redux to do the action and actually change the state? that's where "reducers" come in. 

Redux uses fancy names so what in the world is a reducer? By definition from the documentation 

> A Reducer is a pure function that takes the state of an application and action as arguments and returns a new state

 **Pure functions???** 
Pure functions are functions that will always return the same output whenever they are given the same input. 
But isn't that what all functions do? returning the same results? well..., not really

consider these two functions 

```js
const functionA = (number)=>{
  const sum = number + 2;
  return sum;
};

let x = 2 // keep attention here
const functionB = (number)=>{
  const sum = number + x;
  return sum;
}
```

these two functions may look like they are doing the same but `functionA` is a pure function while `functionB` is an impure function. This is because `functionA` will always return the sum when the same number is passed
On the other hand but `functionB` is depending on `variable x` and if this value is changed `functionB` will return a different sum. Another important behaviour of a reducer is that it should not change the values that are passed to it as input 

There is more to pure functions, I recommend that you read these to articles to understand further [article1](https://blog.greenroots.info/what-are-pure-functions-and-side-effects-in-javascript) [article2](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976) 

Back to the definition of a Reducer 
> A Reducer is a pure function that takes the state of an application and action as arguments and returns a new state

A reducer is just a function that will take the initial state and the action we want and it will perform the action we want, and return an updated state. 

A reducer need to be pure so that it will always walk in a consistent way.

A reducer look something like

```js
const reducer = (state, action)=>{
  // do action ...
  return newState
}
```
let's use an example of a counter app that stores the value of the counter and we can have an action to increment or decrement the number by one 

We can have 0 as our initial value of the counter

```js
const state = {
 count: 0
}
```
we can have our actions like 

```js
const incrementAction = {
type: 'INCREMENT'
}

const decrementAction = {
type: 'INCREMENT'
}
```
Let's now create a reducer that will take a state and an action to return a new state. When we pass the increment action we will increase the current state by 1 and when we pass the decrement action we decrement it by 1.
We will use switch statements to check which action we have and return the new value accordingly

```js
const reducer = (state, action) => {
  switch (action.type) { 
    case 'INCREMENT': {
      const newState = { ...state };
      newState.value = state.value + 1;
      return newState;
    }
    case 'DECREMENT': {
      const newState = { ...state };
      newState.value = state.value - 1;
      return newState;
    }
  }
};
```
Let's break the code line by line 

- `const reducer = (state, action)`: We are creating a reducer function that takes the initial state action object as we saw from the definition

- `switch (action.type)` As we have two actions we are using the switch statement to check the type of the action. You can also use `if-else` statements if you want to.
- `const newState = { ...state }`: **this is the most important part** a reducer is a pure function and will NEVER mutate the state passed to it as an argument instead we create a new object and copy the previous state using [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax). we are just creating a new object and copy everything from the state this means that `newState` and `state` are different objects but they have the same values.

- `newState.value = state.value + 1`: We are changing the `value` field of newState to be the previous state value incremented or decremented by one according to the action type
- `return newState`: we are returning the new state as a reducer should return the new state

the above code can be simplified to be 
```js
const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, value: state.value + 1 };
    case 'DECREMENT':
      return { ...state, value: state.value - 1 };
  }
};
```
**4. Redux store**
Now we have a state, we have actions that describe what to do with the state, and we have a reducer function that implements our action and returns the new state. It looks like we have everything we need we just need better management of all of this code. 

Basically, we want that whenever we call the reducer function and update the state, the new state should replace the old state and be our current state so the next time we perform another change we have a track of how the state changed in our app. 
To achieve this we need to have everything in the same place which is where the `Redux store` comes in. 
The `Redux store` is like a real-life store that holds records of how the state had changed in your application. For example, when a user login the state changes, and when they log out the state will change again, Redux store will keep a track of these changes so that if anything goes wrong we can see exactly what happened and where it happened.

in Redux to access the store we need to create it first, the store is created using the function `createStore()` and this function provides us with functions that we will use to access and manipulate the state

In this guide, we will be focusing on its two functions `getState()` and `dispatch()`

- `getState()`: when you run this function the store will return the current value of the state and this value will always be the updated state. 

- `dispatch()`: In Redux you don't really call the reducer and pass the action directly as we have been doing before, instead you pass the action to the `dispatch` function, and the store will have access to the reducer and the state itself and it will do everything for you. 

this means that you don't need to worry about what's in the state you just dispatch (send) an action to the store, the store will call the reducer and pass the state and the action you dispatched. the reducer will do its work as we saw earlier and when it returns to the new state the store will automatically update the state to this new state.

It's like the way you go to the bank and you have an action of depositing money to your account the cashier will take your money do her work and add the new amount to your account with no effort done on your end

Don't worry if this you are confused by all of this, let's see all in action as we build our simple banking app


**PUTTING EVERYTHING TOGETHER: SIMPLE BANKING APP**

Let's use what we learned to build a simple banking app where someone creates accounts, view their balance, deposit, or withdraw money from their account 

follow these steps

**1. Create a project**
create a folder and open it in VS Code initialize a node project by running 
```js
npm init -y
```
- in the `package.json` add a `type` field and set it value to `"module"` as we will be using imports and export later

**2. Install Redux**

- install Redux by running the following command
```js
npm install redux

// using yarn

yarn add redux
```
**3. Create a redux store**
- create a folder called `redux` and that's where our redux code will be 
- in the redux folder create a file and name it `store.js` this where we will configure our Redux store
- in the 'store.js' file add the following code 
```js
import { legacy_createStore as createStore } from 'redux';

const store = createStore();
```
we are importing createStore from redux and we are creating a new store by invoking that function the `createStore` function

**4. Create a initial state**
Let's have the initial state of our application let's say someone just created a new bank account and their basic information will be our object 

- in the `store.js` right before we create the `store` variable we will add a variable of the initial state and will pass our initial state into the store so that it will store it for us 
the store.js should look like

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

const initialState = {
  accountOwner: 'John Doe',
  address: 'Miami',
  balance: 0,
};
const store = createStore(initialState);

export default store;
```
- we are creating an initial state that includes basic information of the owner and their balance is 0$ as they just created a new account and they don't have money yet.

**5. Create action using action creator**
Remember the actions and action creators we talked about earlier right? actions are object and action creators are function that return these objects

- in the redux folder create file called `actions.js` and  we will add our action creators 
- let's create an action for Depositing money , withdrawing money, and changing address

in your actions.js add the following code

```js
export const depositAction = (amount) => {
  return {
    type: 'DEPOSIT',
    payload: amount,
  };
};

export const withdrawAction = (amount) => {
  return {
    type: 'DEPOSIT',
    payload: amount,
  };
};

export const changeAdressAction = (newAdress) => {
  return {
    type: 'CHANGE_ADRESS',
    payload: newAdress,
  };
};

```
we are creating action creator functions that just return action with type and the payload the value we passed in 
for instance the `depositAction` will return an action with type `DEPOSIT` and a payload of the amount you passed in.

**6. Create a reducer**
in the redux folder create a `reducer.js` file which will contain our reducer

- in the `reducer.js` add the following code

```js
const reducer = (state, action) => {
  switch (action.type) {
    case 'DEPOSIT':
      return { ...state, balance: state.balance + action.payload };
    case 'WITHDRAW':
      return { ...state, balance: state.balance - action.payload };
    case 'CHANGE_ADRESS':
      return { ...state, address: action.payload };
    default:
      return state;
  }
};
export default reducer;
```
- As always it's important that the reducer doesn't mutate the state passed. We create a new object and copy everything in the previous state and change the field we want to change
- in this case when the action is `DEPOSIT` we will change the balance to add amount in the payload to previous balance. the same thing with `WITHDRAW` instead we subtract amount in the payload from previous balance
- when the action is `CHANGE_ADRESS` we will only change the address field to the new address from the payload
- If the action is not known by default we will do nothing we just return previous state unchanged

**7. Pass the reducer to the store**
Remember that we don't have to do anything ourselves the redux store will do everything for us therefore we need to provide the reducer to the store.

- back to the `store.js` import the reducer function and pass it to the `createStore` function.


```js
import { legacy_createStore as createStore } from 'redux';
import reducer from './reducer.js';

const initialState = {
  accountOwner: 'John Doe',
  address: 'Miami',
  balance: 0,
};
const store = createStore(reducer, initialState);

export default store;

```

- we are importing reducer function from `reducer.js` and pass it to the `createStore` function along with the initial state we had before **Note** that the reducer should be passed first as `createStore` function expects the reducer to be the first argument

That's all configurations we need now lets test how everything works

**8. Testing**

in the root folder create an `index.js` file and import the store and actions from redux folder. 

- in the `index.js` add the following code

```js
import {
  changeAdressAction,
  depositAction,
  withdrawAction,
} from './redux/actions.js';
import store from './redux/store.js';

console.log('initialState:');
console.log(store.getState());
//
store.dispatch(depositAction(500));
console.log('New state after deposit:');
console.log(store.getState());
//
store.dispatch(changeAdressAction('Paris'));
console.log('New state after change address');
console.log(store.getState());
//
store.dispatch(withdrawAction(300));
console.log('New state after withdraw');
console.log(store.getState());

```

- to test everything we are just consoling the state by using `store.getState()` remember that `getState` returns our current state
- we are dispatching actions by using `store.dispatch()` and we pass in the function we want to dispatch 
- after dispatching an action we are consoling the state again to see changes 

- Run `node index.js` in the terminal and you should see the following output


![terminal output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6coeu2davjalr4mz3wqs.png)
- you can see that after dispatching an action redux did updated our state 

There you have it! you now understands the basics of Redux In the following article in this series we will look into how to use `Redux-toolkit` to write cleaner code and integrate Redux in a real redux app that is more interactive. 
 
For reference you can find code mentioned in this article on this [github repo](https://github.com/Yvad60/blog-code-references/tree/redux-simplified)