First Day Guide to Redux

Tags: react, redux, webdev, codenewbie
Published: 2019-08-22 14:35:57

I just learned Redux  , and i am here to share what are the things that made me understand what's going on ... 

##let's start with why to use Redux: 

There is interesting discussion in [stackoverflow](https://stackoverflow.com/questions/51064041/why-we-need-redux-in-react) that explains why and when do we need Redux.

In addition to that :
let's say an app with 50 components with their own states that communicate with each other and update each other's state .  

  ![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/u4jh8mkvtnzrhzdfwtam.png) 
 
Now , in the first tree , States of the app become so convoluted and confusing  , whereas in second tree , it's pretty clean because of the master state . Components send requests to update master state and stage changes of master state flow down to component . 

###Installation:
**Consideration:** you are already inside react project and have yarn installed .You can also use npm but i prefer yarn .

     yarn add redux react-redux
###Store , Reducer , Action
1. STORE:
     Store is basically where entire state of the app lives . This is just one big object.Only way to change the state is to dispatch an action for it . 

2. Action:
     Action is just an object with type and payload that is sent or dispatched from view which are sent to Reducer . 

3. Reducer:
    Reducer is a pure function that reads the state and action.It handles how to update the state based on the action props and returns the next state .

    ![Redux flow](https://i.stack.imgur.com/LNQwH.png)
    <figcaption>Fig: Redux flow</figcaption>


###Create Store :

Import createStore from redux in your index.js file .
```javascript
 import { createStore } from 'redux'; 
```
Remember that there is only one store in an Application .

Now create a store .
```javascript
const store = createStore(
  reducer,
  {
    products: [{ name: "iphone" }],
    user: ["michael"]
  },
  allenhancer
);
```

createStore() function takes three arguments,first of which is reducer function , second is initial or pre-loaded state and last is store enhancer.

we will talk about store enhancer next time  , for now let's write this  
```javascript
const allenhancer = window.devToolsExtension && window.devToolsExtension();
```
This is for Redux devtools . You can add it on your browser extension. For [ chrome ] (https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en) , you can add it from here .  
###Create and dispatch an action :

Action is just an object with type and payload , let's create it :
```javascript
const action = {
type:'changestate' ,
payload:{
    newState:'New state'
 }
};
```
Now dispatch an action object with store object that we just created above :
```javascript
store.dispatch(action);
```

###Define a reducer function and handle the action props:
```javascript
function reducer(state , action){
if(action.type=== 'changeState'){
   return action.payload.newState;
}
return 'default-value';
}
```

Reducer function takes two arguments , state and action which is dispatched by store and return next state . 

you can console the store state with 

```javascript 
console.log(store.getState());
```

where we can see that state has been changed to 'New State' . **store.getState()** returns the current state tree of your application . It is equal to last value returned by store's reducer. 

###Dividing state with multiple Reducer : 
Putting all your updates or handling logic in single reducer function can become unmanageable . So , what we do is split the logic into multiple functions and call those functions from parent function . 
All functions have <code>(state , action)</code> as parameter .
You may be thinking " how to call different reducer if we have multiple one ?" . Well,here comes the rescuer : <code>combineReducers()</code> .
For that , import it from redux . The import line from above looks this :

```javascriptimport { combineReducers, createStore } from 'redux'```

###Refactoring of Reducer function : 
This is our reducer function that add user or product into our state , and return new state with payload added to product or user as per 'type' :  
```javascript
function reducer(state = "", action) {
 switch (action.type) {
  case "UPDATE_USER":
    let temp_state_user = Object.assign({}, state);
    temp_state_user.user.push(action.payload);
    return temp_state_user;
  case "UPDATE_PRODUCT":
    let temp_state_product = Object.assign({}, state);       
    temp_state_product.product.push(action.payload);
    return temp_state_product;
  default:
      return state;
   }
  }
```
Reducer function handles the action on calling dispatch as : 
```javascript
store.dispatch({ type: "UPDATE_USER", payload: "PRAVIN" });
console.log(store.getState());
```
console.log() gives console output as :
![Console output after dispatch call](https://thepracticaldev.s3.amazonaws.com/i/5c64p0w9larumwhhk23s.png)
Reducer function above takes switch operation to handle user and products update inside same function .This may be clumsy if this grows . We now want to take slice of this render logic ,and put it inside individual function . <code> combineReducers() </code> provide us this functionality to combine different reducing logic and make parent render function which can be made called by store on dispatch .

*Let's refactor above render function*
```javascript
const initialState = null;
function user_reducer(state = initialState, action) {
  switch (action.type) {
    case "UPDATE_USER":
      let users = state;
      users.push(action.payload.user);
      return users;
    default:
      return state;
  }
}
function product_reducer(state = initialState, action) {
  switch (action.type) {
    case "UPDATE_PRODUCT":
      let temp_state_product = Object.assign({}, state);
      temp_state_product.push(action.payload);
      return temp_state_product;
    default:
      return state;
  }
}
```

combineReducer() combines both reducers and return parent reducer that can be attached with store.
```javascript
const allReducers = combineReducers({
  products: product_reducer,
  user: user_reducer
});
```

and now we have store creation code as : 
```javascript
  const store = createStore(
  allReducers,
  {
    products: [{ name: "iphone" }],
    user: ["michael"]
  },
  allenhancer
);
```

This also gives the same result in console after <code> console.log(store.getState())</code>

That's it for now , 

This is not good way to write all code inside index.js so next time we will start with directory/file hierarchy and about passing this state to view or component .