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 ๐