Why Redux Toolkit & not Redux?
We'll just have to install 2 packages @reduxjs/toolkit (Core) & react-redux (Bridge between React & Redux TKT).
Write / Update Slice of Store
Whenever you click an Add To Cart Button => It DISPATCHES an Action => which will call a REDUCER Function => Which Updates the Slice of the Store
Create Store
configureStore comes from @reduxjs/toolkit
import { configureStore } from "@reduxjs/toolkit";
import cartReducer from "./cartSlice";
const appStore = configureStore(
{
// reducer of entire store => consists of reducers of all its slices (each slice will have
its own reducers)
reducer : { // App's Store reducer
cart: cartReducer, // cart slice reducer
// user: userReducer // user slice reducer
}
}
);
export default appStore;
Create A Slice (Cart Slice)
createSlice also comes from @reduxjs/toolkit
import { createSlice, current } from "@reduxjs/toolkit";
const cartSlice = createSlice({
name: 'cart',
initialState: {
items: []
},
reducers: {
addItem : (state, action)=>{
//! We have to Mutate the state here (Directly modifying)
//! Redux TKT uses IMMER Behind the Scenes
state.items.push(action.payload);
},
removeItem: (state, action) =>{
state.items.pop();
},
clearCart : (state)=>{
// no need for action payload here as we are just emptying the cart
console.log(current(state)); // To get Value of state we use current
(or else it will give Proxy Object)
state.items.length = 0; // [] - ALWAYS DO THIS WAY ✅ & not state = [] ❌
return []; // This also works✅ As RTK advises you to Mutate the state directly
or return new State
}
}
});
export const {addItem, removeItem, clearCart} = cartSlice.actions;
export default cartSlice.reducer;
1. We export all Actions from here
2. We export Cart Slice's reducer
Menu Items
<{itemCards.map((item)=>
<li key={item.card.info.id}>{item.card.info.name}
<button onClick={()=>{handleAddToCart(item)}}>Add +</button>
<button onClick={()=>handleRemoveItem(item)}>Remove -</button></li>)}
useDispatch comes from react-redux
import { useDispatch } from "react-redux";
import { addItem, removeItem } from "../utils/cartSlice";
const dispatch = useDispatch();
const handleAddToCart = (item)=>{
dispatch(addItem(item)); // action.payload will be equal to this item behind the scenes
}
const handleRemoveItem = (item)=>{
dispatch(removeItem(item));
}
Provider comes from "react-redux" - This pkg provides A link between React & Redux
import { Provider } from "react-redux";
const AppLayout = () => {
return (
<Provider store={appStore}>
<div className="app">
<Header />
<Outlet />
</div>
</Provider>
);
}
Here you want to use Redux Store in your entire App. That's we wrapped over App
You can even use it in A Component only, Just wrap this Provider over it
clearCart Action on Cart Page
import { useDispatch, useSelector } from "react-redux";
import { clearCart } from "../utils/cartSlice";
const Cart = ()=>{
const cartItems = useSelector((store) => store.cart.items); //Subscribed to CartSlice of Store
const dispatch = useDispatch();
const handleClearCart = () => {
dispatch(clearCart());
}
If You want to Read / Subscribe Data from the Slice of the Store
Suppose you want to show Cart Qty from Cart Slice of the Store in Header
Then Your Header component should be subscribed to that Slice Of the Store using Selector
This useSelector will give you access to the entire Store. You can select the portion/slice of the store eg: Cart
import { useSelector } from "react-redux";
const cartItems = useSelector((store) => store.cart.items); //Subscribing to Cart Slice ✅✅✅
This above variable will only update when the cart items are changed! ✅🔥
If you try to access the entire store ❌
const store = useSelector((store) => store); // Subscribing to the entire store ❌❌❌
This variable will keep on updating everytime when anything from the Store updates ❌
This is very less efficient.Why?
When our Application becomes Big. Our Store size also increases. So any random changes in the store might affect this Component as well. If subscribed to the Entire Store
If something is happening inside some other Slice of the Store. Eg: When user logs In. Then we don't want our Variable inside the Cart to get updated as well.
So We'll Just subscribe to the required smaller portion of the store only, for BETTER PERFORMANCE!!! Tell this to your interviewer ;)
It is useSelector so it means you have to select only a small Portion / Slice of the Store
Extra Info:
Vanilla Redux (older way) didn’t allow us to Mutate the State directly. But with Redux Toolkit WE HAVE TO MUTATE THE STATE.
*Redux TKT handles everything behind the scenes (making a copy of the state and returning it). It uses Immer Library to do all this. [immerjs.github.io/immer/*](https://immerjs...
We as developers don't have to do it. ❤️🔥
Redux Dev Tools
Thank you! Stay tuned for my upcoming blogs 🔥