DEV Community

Cover image for First Day Guide to Redux
Pravin Poudel
Pravin Poudel

Posted on • Updated on

First Day Guide to Redux

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

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
Enter fullscreen mode Exit fullscreen mode

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

    Fig: Redux flow

Create Store :

Import createStore from redux in your index.js file .

 import { createStore } from 'redux'; 
Enter fullscreen mode Exit fullscreen mode

Remember that there is only one store in an Application .

Now create a store .

const store = createStore(
  reducer,
  {
    products: [{ name: "iphone" }],
    user: ["michael"]
  },
  allenhancer
);
Enter fullscreen mode Exit fullscreen mode

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

const allenhancer = window.devToolsExtension && window.devToolsExtension();
Enter fullscreen mode Exit fullscreen mode

This is for Redux devtools . You can add it on your browser extension. For chrome , you can add it from here .

Create and dispatch an action :

Action is just an object with type and payload , let's create it :

const action = {
type:'changestate' ,
payload:{
    newState:'New state'
 }
};
Enter fullscreen mode Exit fullscreen mode

Now dispatch an action object with store object that we just created above :

store.dispatch(action);
Enter fullscreen mode Exit fullscreen mode

Define a reducer function and handle the action props:

function reducer(state , action){
if(action.type=== 'changeState'){
   return action.payload.newState;
}
return 'default-value';
}
Enter fullscreen mode Exit fullscreen mode

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

you can console the store state with

console.log(store.getState());
Enter fullscreen mode Exit fullscreen mode

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 (state , action) as parameter .
You may be thinking " how to call different reducer if we have multiple one ?" . Well,here comes the rescuer : combineReducers() .
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' :

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;
   }
  }
Enter fullscreen mode Exit fullscreen mode

Reducer function handles the action on calling dispatch as :

store.dispatch({ type: "UPDATE_USER", payload: "PRAVIN" });
console.log(store.getState());
Enter fullscreen mode Exit fullscreen mode

console.log() gives console output as :
Console output after dispatch call
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 . combineReducers() 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

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

combineReducer() combines both reducers and return parent reducer that can be attached with store.

const allReducers = combineReducers({
  products: product_reducer,
  user: user_reducer
});
Enter fullscreen mode Exit fullscreen mode

and now we have store creation code as :

  const store = createStore(
  allReducers,
  {
    products: [{ name: "iphone" }],
    user: ["michael"]
  },
  allenhancer
);
Enter fullscreen mode Exit fullscreen mode

This also gives the same result in console after console.log(store.getState())

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 .

Top comments (3)

Collapse
 
dance2die profile image
Sung M. Kim

Thank you for the post, Pravin.

Would you be be able to update the post with a syntax highlight as to improve the readability? Refer to the Editor Guide for more info.

Collapse
 
voralagas profile image
Pravin Poudel

Thanks Sung for comment .

I did code highlighting ... Thanks again for comment and going through
this post .

Collapse
 
dance2die profile image
Sung M. Kim

Thank you, Pravin 😀