Home  >  Q&A  >  body text

Navigation bar component does not re-render on state change

I'm trying to create a shopping cart. I created a context and passed the state as value when pressing the increment and decrement buttons on the cart, my item count is changing but when I use the same context in the navigation bar component, in the cart The total number of items will not change. I am attaching the code snippet below

This is where I create the 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);

Below is my useContext provider.

<CartContext.Provider value={{...state}}>
<ContextCart removeItems={removeItems} increment={increment} decrement={decrement}/> </CartContext.Provider>

The value of the status comes from useReducer, it is updating everything is fine

This is how I use useContext Hook in the navigation bar to get the total number of items in the shopping cart

const cartItems = useContext(CartContext);

return (
  <div>{cartItems.totalItems}</div>`
)

But whenever the status changes, the navigation bar does not re-render the updated total number of items in the cart, please help me.

This is my useReducer function and everything it updates. I've checked its functionality by executing console.log(). Everything it returns is fine, including 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};
    }```

P粉037880905P粉037880905376 days ago421

reply all(1)I'll reply

  • P粉348915572

    P粉3489155722023-09-08 09:44:53

    When you use useReducer it returns the current state, right? As far as you are concerned, the state is an object. Therefore, you can get totalItems directly from that state object. For example:

    const [state, dispatch] = useReducer(cartReducer, initialState);
    
    // Here's where we get totalItems from the state
    const { totalItems } = state;

    So this way, totalItems is pulled directly from the state object and you can use it wherever you need it.

    reply
    0
  • Cancelreply