This is cart page of a ecommerce site. Here I want to get the value of each indivisual counter value and multiply that with their respective price and show it into final checkout value. Here, i had hardcoded $160 but I want to make that dynamic. How can I do that or what would be best approach to achieve that.
My cart page
import React, { useState } from 'react'
import { RiDeleteBin6Line } from "react-icons/ri"
import Counter from '../../Components/Counter/Counter'
const Products = ({ cartdetails }) => {
const [value, setValue] = useState()
return (
<div className=' grid grid-cols-12 gap-4'>
{cartdetails.length === 0 ?
<div>No items in cart</div>
:
<div className=' col-span-8'>
{
cartdetails.map((data, index) => {
return (
<div className=' bg-gray-100 px-4 my-4 py-4'>
<div className=' flex justify-between'>
<img className=' w-24 h-24' src={data.productdetails.image} alt="" />
<div className=''>
<div className=' font-semibold text-lg'>
{data.productdetails.name}
</div>
<div className=' text-gray-400 text-sm'>
Color : {data.cartItems.color}
</div>
</div>
<div>
<div className='font-semibold text-lg'>${data.productdetails.price} USD</div>
<div className='text-gray-400 text-sm'>Price</div>
</div>
<div>
<div className=' font-semibold text-lg'>{data.productdetails.stock}</div>
<div className='text-gray-400 text-sm'>In Stock</div>
</div>
<button className=' h-fit text-gray-400'>
<RiDeleteBin6Line />
</button>
</div>
<Counter count={data.cartItems.quantity} {...data.productdetails} />
</div>
)
})
}
</div>
}
<div className=' col-span-4 my-4 '>
<div className=' px-4 py-8 flex flex-col gap-8 bg-gray-100'>
<div className=' flex justify-between'>
<div className=' font-bold'>Total</div>
<div className=' font-semibold'>$160USD</div>
</div>
<div className=' flex justify-end '>
<button className=' btn w-36 font-bold'>Checkout</button>
</div>
</div>
</div>
</div>
)
}
export default Products
Counter Component
import React, { useState } from 'react'
import { HiOutlineMinus } from "react-icons/hi"
import { GoPlus } from "react-icons/go"
import { incrementItem, decrementItem } from '../../redux/cart/changeCartNumber'
import { useSelector, useDispatch } from 'react-redux'
const Counter = ({ count, stock, _id }) => {
const [value, setValue] = useState(count)
return (
<div className='flex font-bold text-xl justify-end'>
<div className=' flex gap-4 bg-white p-2 w-40 justify-between '>
{/* <button className={`${state.value === 1 && "text-gray-400"}`} disabled={state.value === 1} onClick={() => dispatch(decrementItem({ _id, count }))}><HiOutlineMinus /></button> */}
<button onClick={() => setValue(value - 1)} disabled={value === 1} className={`${value === 1 && "text-gray-400"}`} ><HiOutlineMinus /></button>
<div>
{value}
</div>
<button onClick={() => setValue(value 1)} disabled={value === stock} className={`${value === stock && "text-gray-400"}`}><GoPlus /></button>
</div>
</div>
)
}
export default Counter
CodePudding user response:
I don't know about getting the state back from a map function as it will be quite arduous for me, but why don't you try creating a totalPrice state in Products and then change the value of totalPrice by propDrilling setTotalPrice to Counter which will change its value on each and every change in their inventory (or cart).
const [totalPrice, setTotalPrice] = useState(0)
<Counter totalPrice={totalPrice} setTotalPrice={setTotalPrice} />
In counter you can setTotalPrice(totalPrice {whatever price it is for that specific increament/decreament}
Let me know if it works, I haven't tried it on a map function though. :)
CodePudding user response:
You have to make another state in the parent component that will calculate the total on every child. your code will look like this:
import React, { useState } from 'react'
import { RiDeleteBin6Line } from "react-icons/ri"
import Counter from '../../Components/Counter/Counter'
const Products = ({ cartdetails }) => {
const [total, setTotal] = useState()
return (
<div className=' grid grid-cols-12 gap-4'>
{cartdetails.length === 0 ?
<div>No items in cart</div>
:
<div className=' col-span-8'>
{
cartdetails.map((data, index) => {
return (
<div className=' bg-gray-100 px-4 my-4 py-4'>
<div className=' flex justify-between'>
<img className=' w-24 h-24' src={data.productdetails.image} alt="" />
<div className=''>
<div className=' font-semibold text-lg'>
{data.productdetails.name}
</div>
<div className=' text-gray-400 text-sm'>
Color : {data.cartItems.color}
</div>
</div>
<div>
<div className='font-semibold text-lg'>${data.productdetails.price} USD</div>
<div className='text-gray-400 text-sm'>Price</div>
</div>
<div>
<div className=' font-semibold text-lg'>{data.productdetails.stock}</div>
<div className='text-gray-400 text-sm'>In Stock</div>
</div>
<button className=' h-fit text-gray-400'>
<RiDeleteBin6Line />
</button>
</div>
<Counter setTotal={setTotal} count={data.cartItems.quantity} {...data.productdetails} />
</div>
)
})
}
</div>
}
<div className=' col-span-4 my-4 '>
<div className=' px-4 py-8 flex flex-col gap-8 bg-gray-100'>
<div className=' flex justify-between'>
<div className=' font-bold'>Total</div>
<div className=' font-semibold'>{total}USD</div>
</div>
<div className=' flex justify-end '>
<button className=' btn w-36 font-bold'>Checkout</button>
</div>
</div>
</div>
</div>
)
}
export default Products
And now inside the Counter component you will update that state to calculate the total.
<button onClick={() => {setValue(value - 1); props.setTotal(prev=>prev value-1)}} disabled={value === 1} className={`${value === 1 && "text-gray-400"}`} ><HiOutlineMinus /></button>