skip to Main Content

Every time I display the cart items I want to update the total price and count of the items using the useState function inside the render method. But, immediately after the UI is rendered I get a react error mentioned above.

Is there a better way of doing what I’m trying to achieve without getting the error?

const Cart = () => {
  const cartItems = useItems()
  const firebase = useFirebase()
  //Items count

  //Total amount of the items
  let [total, updateTotal] = useState(0)
  let [count, updateCount] = useState(1)

  //Method to add items to the cart
  useEffect(() => {
    if (!firebase) return
  }, [firebase, cartItems])




  return (
    <Layout>
      <SEO title="Cart" />
      <Navbar count={count} />
      <MDBContainer>
        <MDBCol lg="12" className="">
          <MDBTable responsive className="mt-5 z-depth-1">
            <MDBTableHead>
              <tr className="bg-light">
                <th>
                  <div className="p-1 px-3 text-uppercase font-weight-bold">
                    Product
                  </div>
                </th>
                <th>
                  <div className="p-1 px-3 text-uppercase font-weight-bold">
                    Price
                  </div>
                </th>
                <th>
                  <div className="p-1 px-3 text-uppercase font-weight-bold">
                    Quantity
                  </div>
                </th>
                <th>
                  <div className="p-1 px-3 text-uppercase font-weight-bold">
                    Remove
                  </div>
                </th>
              </tr>
            </MDBTableHead>
            <MDBTableBody id="products-list">
              {cartItems.map(product => {
                updateTotal((total += product.price))
                updateCount((count += 1))
                return (
                  <tr>
                    <td class="px-3 font-weight-normal">
                      {product.name} <span class="d-none">{product.id}</span>{" "}
                    </td>
                    <td width="10%" class="text-center font-weight-normal">
                      {product.price}
                      <span>/kg </span>{" "}
                    </td>
                    <td width="10%" class="text-center font-weight-normal">
                      {product.count}
                    </td>
                    <td width="10%" class="text-center">
                      <div class="px-3 font-weight-normal">
                        {" "}
                        <button
                          class="bg-transparent border-0"
                          id="delete-button"
                        >
                          <i class="fa fa-trash-alt delete-icon"></i>
                        </button>
                      </div>
                    </td>
                  </tr>
                )
              })}
            </MDBTableBody>
            <MDBTableFoot>
              <tr>
                <td className="px-3 text-uppercase font-weight-bold">Total</td>
                <td className="font-weight-bold px-5">&#8377;{total}</td>
                <td className="font-weight-bold pr-2 text-center">{count}</td>
              </tr>
            </MDBTableFoot>
          </MDBTable>
        </MDBCol>
      </MDBContainer>
    </Layout>
  )
}

export default Cart

3

Answers


  1. use blank [] instead of [firebase, cartItems]

    Login or Signup to reply.
  2. Putting [firebase, cartItems] tells react to always re-render if any change is made to these two parametres. So that is why there are too many re-renders.

    Login or Signup to reply.
  3. The below code should work for you:

    const cartItems = useItems();
    // I assume this gives you cartItems.
    
    let [total, updateTotal] = useState(() => {
      if (cartItems) {
        // item object {id: "2", name: "Cucumber", category: "vegetable", price: 50, // //count: 0}
        return cartItems.reduce((acc, elem) => {
          acc += elem.price * elem.count;
          return acc;
        }, 0);
      }
      return 0;
    });
    let [count, updateCount] = useState(cartItems.length);
    
    React.useEffect(() => {
      if (cartItems) {
        updateCount(cartItems.length);
        // item object {id: "2", name: "Cucumber", category: "vegetable", price: 50, // //count: 0}
        const total = cartItems.reduce((acc, elem) => {
          acc += elem.price * elem.count;
          return acc;
        }, 0);
        updateTotal(total);
      }
    }, [cartItems]);
    

    So, basically you need to initiate the state once you get some value from the useItems and then also need to update it when cartItems reference changes

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search