Shamaayil Ahmed

Shamaayil Ahmed

Redux in react

Redux in react

State management for high-end web apps

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

Let's see a complex state management tool used in high end react apps.

TL;DR

So far in recent posts we have discussed about useReducer and useContext hooks, which can't handle any complex data flow so which we move onto a third party dependency called redux which does all complex data flow and management in ease.

State Management

Difficult part of an application so far is considered to be managing the state, which need a lot of engineering, foreseeing things and using a apt approach to solve the problem and here we see a chance for over-engineering which makes this even worse.

We have known state management using;

  • useState for persisting data between renders
  • useReducer for complex state logics
  • useContext to be free from prop drilling or passing state values to each and every node in component tree

Ain't these enough for state management 🤔

Probably contextAPI in combination with useReducer can do things in ease but when it comes to high-end apps where the component tree is so large and the above mentioned duo may become a pain point to developers.

Redux

So for high-end apps there are lot of dependencies avail which solves the problem, here we go for redux for its ease of understanding and a powerful way of managing states.

The best reason to go for redux is when the performance in concerned, as with the whole state is confined within a single object in contextAPI a reload may require a re-render of whole state i.e; the whole app. Which redux v7 solves by spreading the reducers to different files and combining them.

Setup React Redux

Change directory to the root and use the npm command;

npm install redux react-redux

React Redux in action

Let's see a simple application to see redux in action;

Folder structure

src
|_
|_ actions
|       |-index.js
|_reducers
|       |_index.js
|       |_counter.js
|       |_logger.js 
|_index.js
|_App.js

actions/index.js

export const increment = (value) => {  //value given while dispatching
  return {
    type: 'INC',
    payload: value
  };
};
export const decrement = () => {
  return {
    type: 'DEC'
  };
};

export const signin = () => {
  return {
    type: 'SIGN_IN'
  };
};

Here we have two reducers counter and a logger, which we combine together inside the entry point of the file.

reducers/counter.js

const counter = (state = 0, action) => {
  switch (action.type) {
    case "INC":
      return state + action.payload;

    case "DEC":
      return state - 1;
      break;

    default:
      return state;
  }
}

export default counter;

reducers/logger.js

const logger = (state = false, action) => {
  switch (action.type) {
    case "SIGN_IN":
      return !state;

    default:
      return state;
  }
}

export default logger;

reducers/index.js

import counter from './counter'
import logger from './logger'

import { combineReducers } from 'redux';

const OurReducers = combineReducers({
  counter, logger
})

export default OurReducers;

Here the store is created and made avail to the root component with all the reducers.

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';   

import { createStore } from 'redux';  //store contains all the state and functionalities
import OurReducers from './reducers'  //here it is combined reducers 

import { Provider } from 'react-redux';  

const OurStore = createStore(OurReducers);  //creating a store with all our reducers

ReactDOM.render(
  <React.StrictMode>
    <Provider store={OurStore}> //make available to whole component tree
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

Here we consume the data from the store.

src/App.js

import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { increment, decrement, signin } from './actions'

const App = () => {
  const counter = useSelector(state => state.counter);
  const logger = useSelector(state => state.logger);

  const dispatch = useDispatch();

  return (
    <div>
      <h1>Counter: {counter}</h1>
      <button onClick={() => dispatch(increment(10))}>+</button> //increment by 10
      <button onClick={() => dispatch(decrement())}>-</button>

      <div>
        {logger ? <h3>Secret Information exclusive for members</h3> : ''}
        <button onClick={() => dispatch(signin())}>Sign IN</button>
      </div>
    </div>
  )
}

export default App

So that's a simple illustration when the app increases in size the data flow is more complex and redux could be on our side and would make more sense.


Major Takeaway

State management is something to look for so it's necessary to use the apt approach, use redux only for high-end app.

Let's connect 🔗

Catch me here 👇


Hope you all liked the post, share your impressions and queries below 🙌

 
Share this