Home > Enterprise >  ReactJS UI Does Not Update The State
ReactJS UI Does Not Update The State

Time:05-19

I am trying to make a simple e-commerce app. When a user goes to cart section and try to increase or decrease quantity, it changes the state but remains same on the page. I need to go back and go cart again to update. How can it change dynamically?


function CardItem() {
    const {cart, setCart} = useContext(ProductContext)

    const addQuantity = (cartItem) => {
      return cart.map((item) => (
        cartItem.id === item.id ? item.quantity = item.quantity   1 : item
      ))
    }

    const removeQuantity = (cartItem) => {
        cart.map((item) => (
          cartItem.id === item.id ? item.quantity = item.quantity - 1 : item
        ))
      }

  return (
            {
              cart.map((cartItem) => (
                <tr key={cartItem.id}>
   
                <td >
                  <div >
         <div >
                     <button className='increase' onClick={() => removeQuantity(cartItem)}>
                     -</button>
                     {cartItem.quantity}
                     <button className='increase' onClick={() => addQuantity(cartItem)}> </button>
                     </div>
                   </div>
            </td>
        </tr>
      ))
  })}

CodePudding user response:

Issue

  • The code in your snippet isn't calling setCart to update any state.
  • The add/remove quantity handlers are just mutating the cart state object. Don't mutate React state.

Solution

Use the setCart state updater function to enqueue a state update to trigger a rerender to view the updated state. Use a functional state update to correctly update from the previous state and remember that you should shallow copy any state that is being updated.

Example:

function CardItem() {
  const { cart, setCart } = useContext(ProductContext);

  const addQuantity = (cartItem) => {
    setCart(cart => cart.map(item => cartItem.id === item.id
      ? {                            // <-- new item object reference
        ...item,                     // <-- shallow copy item
        quantity: item.quantity   1, // <-- update property
      }
      : item
    ));
  };

  const removeQuantity = (cartItem) => {
    setCart(cart => cart.map(item => cartItem.id === item.id
      ? {
        ...item,
        quantity: item.quantity - 1,
      }
      : item
    ));
  };

  return (
    {cart.map((cartItem) => (
      <tr key={cartItem.id}>
        <td >
          <div >
            <div >
              <button className='increase' onClick={() => removeQuantity(cartItem)}>
                -
              </button>
              {cartItem.quantity}
              <button className='increase' onClick={() => addQuantity(cartItem)}>
                 
              </button>
            </div>
          </div>
        </td>
      </tr>
    ))
  });
}

Since adding/removing is essentially the same action, it's common to use a single function to handle both and pass in the quantity you want to adjust by.

function CardItem() {
  const { cart, setCart } = useContext(ProductContext);

  const addQuantity = (id, amount) => () => {
    setCart(cart => cart.map(item => cartItem.id === id
      ? {
        ...item,
        quantity: item.quantity   amount,
      }
      : item
    ));
  };

  return (
    {cart.map((cartItem) => (
      <tr key={cartItem.id}>
        <td >
          <div >
            <div >
              <button
                className='increase'
                onClick={addQuantity(cartItem.id, -1)}
              >
                -
              </button>
              {cartItem.quantity}
              <button
                className='increase'
                onClick={addQuantity(cartItem.id, 1)}
              >
                 
              </button>
            </div>
          </div>
        </td>
      </tr>
    ))
  });
}

CodePudding user response:

I will recommend using reducers with context to manage state. Something like below a new CartReducer with ADD and REMOVE item etc. actions

const [state, dispatch] = useReducer(CartReducer, initalState);

const addToCart = (id) => {
dispatch({ type: ADD, payload: id});
};

const showHideCart = () => {
dispatch({ type: SHOW, payload:'' });
};

const removeItem = (id) => {
dispatch({ type: REMOVE, payload: id });
};

You can refer this project if it helps shopping-cart-with-context-api

  • Related