I am trying to create a shopping cart. I have created a context and passed the state as a value on pressing increment and decrement button on the cart my items count in the are changing but total number of items in the cart is not changing when I use the same context in navbar component. I am attaching the code snippets below
This is where I create my context
const initialState:initialType = {
cartItems:cartItems,
totalItems:cartItems.reduce((accumulator, object) => {
return accumulator + object.quantity
}, 0),
totalAmount:0
}
export const CartContext = createContext<initialType|null>(initialState);
This down below is my provider for useContext.
<CartContext.Provider value={{...state}}>
<ContextCart removeItems={removeItems} increment={increment} decrement={decrement}/> </CartContext.Provider>
The value of state is coming from useReducer which is updating everything fine
this is how I used my useContext Hook in Navbar to fetch total number of Items in cart
const cartItems = useContext(CartContext);
return (
<div>{cartItems.totalItems}</div>`
)
but whenever the state changes the navbar never re-renders with updated total number of items in cart kindly help me out.
This is my useReducer Function and its updating everthing well. I have checked its functionality by performing console.log(). and it is returning everything well, which also includes state.totalItems.
type actionType={
type:string,
payload:string
}
export const reducer = (state:initialType ,action:actionType) => {
if(action.type === "Delete" ){
return {
...state,
cartItems:state.cartItems.filter((currentElement)=>{
return currentElement.id != action.payload
})
}
}
if (action.type === 'increment'){
state.cartItems.forEach((element)=>{
if (element.id === action.payload){
element.quantity++;
state.totalItems++
}
})
return {...state};
}
if (action.type === 'decrement'){
state.cartItems.forEach((element)=>{
if (element.id === action.payload){
element.quantity--;
state.totalItems--;
}
})
console.log(state)
return {...state};
}
return {...state};
}```
2
Answers
The hiccup you’re experiencing might be because your totalItems isn’t updating when your cartItems state changes.
You see, you’re calculating totalItems only once, during the initial state setup. So, even if cartItems changes later, totalItems doesn’t get recalculated.
A simple fix could be moving the totalItems calculation into your reducer function. This way, it gets recalculated every time an action is dispatched.
Don’t forget to dispatch the ‘INCREMENT’ and ‘DECREMENT’ actions in your increment and decrement functions.
With this tweak, your totalItems should stay in sync with the cartItems, and your Navbar should update correctly. Give it a shot!
When you’re using
useReducer
, it gives you back the current state, right? And in your case, that state is an object. So, you can just grabtotalItems
straight from that state object. For example:So, with this,
totalItems
is pulled right out of the state object, and you can use it wherever you need it.