I need to dynamically update the total when an item is added
selectedProducts is the array being updated onClick with the selected item, the item includes the price (in the object: 'price'), i need to get the price of the total items, and update totalPrice accordingly.
* I am trying to keep everything in one function if possible *
class App extends Component {
state = {
products: products,
selectedProducts: [],
totalPrice: 0,
};
handleQuantityChange = id => {
const carsSelected = this.state.selectedProducts;
const price = products.map(id => id.price).find((id)=> {
return id
} )
const priceAddition = price
const oldPrice = this.state.totalPrice;
const newPrice = oldPrice + priceAddition;
this.setState({
selectedProducts: [...carsSelected, id],
totalPrice:newPrice,
});
};
You can simplify your method with a functional form of setState:
handleQuantityChange = id => {
const product = products.find(product => product.id === id)
this.setState(state => ({
selectedProducts: [...state.selectedProducts, id],
totalPrice: state.totalPrice + product.price,
}));
};
Because find method does return matched record as array object.
so you have replace above your find method line with these lines
const product = products.find(product => product.id === id)
const {price=0}=product[0] && product[0] || {};
ive solved the issue, all i had to do was:
handleQuantityChange = id => {
const carsSelected = this.state.selectedProducts
const oldTotal = this.state.totalPrice
const newPrice = id.price + oldTotal
this.setState({
selectedProducts: [...carsSelected, id],
totalPrice: newPrice
});
};
thanks for everyone help
Related
hello I've been having a problem with checking if an item already exists in the cart. if so I want only the quantity to be updated for some reason it keeps adding the item as a new item even if it exists. This is what I've been doing:
// Adding Items to cart
const onAdd = (product, quantity) => {
const checkProductInCart = cartItemsFromLocalStorage.find((item) => item.id === product.id);
setTotalPrice((prevTotalPrice) => (prevTotalPrice + Math.round((product.price * quantity)*100)/100));
setTotalQuantities((prevTotalQuantities) => prevTotalQuantities + quantity);
if(checkProductInCart) {
// eslint-disable-next-line
const updatedCartItems = cartItemsFromLocalStorage.map((cartProduct) => {
if(cartProduct.id === product.id) return {
...cartProduct,
quantity: cartProduct.quantity + quantity
}
})
setCartItems(updatedCartItems);
} else {
product.quantity = quantity;
setCartItems([{ ...product }, ...cartItems]);
}
toast.success(` ${product.name} added to the cart.`);
}
Seems like the issue is on your cartItemsFromLocalStorage.map implementation. The map function should return the product even if it isn't the one you're looking to update. Try updating that map to
cartItemsFromLocalStorage.map((productOnCart) => {
if (productOnCart.id === product.id) {
return { ...productOnCart, cartProduct.quantity + quantity }
}
return productOnCart
})
If you don't return anything your list will be full of undefined objects
In strict Mode, React runs twice to detect side effects. So I think I should not turn the strict Mode off, I should make sure that when running twice, the output still correct.
There is a product , when I add qty 3, run twice , the output will be 1 + 3 + 3 = 7.
It's a simple cart logic. When no item ,create an item and concat() it. It there is this item (qty>1 or findIndex() > 0), find it ,and edit its quantity. However, when run twice, add quantity will run twice too. How can I solve the problem?
export const CartContextProvider = props => {
const defaultCart = { items: [], qty: 0, total: 0 }
const cartReducer = (state, actions) => {
if (actions.type === 'SUBMIT') {
const [id, qty, price] = [
actions.item.id,
actions.item.qty,
actions.item.price
]
//ckeck if pd already exists
const itemIndex = state.items.findIndex(el => {
return el.id === id
})
// if no item ,add first item to cart
if (itemIndex === -1 && +qty > 0) {
const newItem = {
id: id,
qty: +qty,
price: +price
}
const updatedItems = state.items.concat(newItem)
const updatedQty = state.qty + +qty
const updatedTotal = state.total + +qty * +price
console.log(newItem.qty)
return { items: updatedItems, qty: updatedQty, total: updatedTotal }
} else {
console.log('run')
let findItem = state.items[itemIndex]
const updatedItem = {
id: id,
qty: findItem.qty + +qty, // here will run twice.
price: +price
}
const stateItems = state.items
stateItems[itemIndex] = updatedItem
console.log(updatedItem.qty)
const updatedQty = state.qty + +qty
const updatedTotal = state.total + +qty * +price
return { items: stateItems, qty: updatedQty, total: updatedTotal }
}
}
return defaultCart
}
const [cart, dispatchCart] = useReducer(cartReducer, defaultCart)
function cartSubmitHandler (id, qty, price) {
dispatchCart({ type: 'SUBMIT', item: { id: id, qty: qty, price: price } })
}
return (
<CartContext.Provider
value={{
cart: cart,
cartSubmitHandler: cartSubmitHandler
}}
>
{props.children}
</CartContext.Provider>
)
}
export default CartContext
The culprit is
const stateItems = state.items
should be :
const stateItems = [...state.items]
I slightly change the name of variables. Final code is presenting down below.
I am trying to retrieve an all documents of which document ID is within the given array. I have no issues retrieving the list of documentIDs and storing in the array. However, I am not sure on how to retrieve the documents of which ids are in the array. Please help Thanks!
portfolio doc:
docId{
docId: docId,
...
}
const getData = (bookmarkIds) => {
console.log("this is " )
console.log(bookmarkIds)
console.log("entering" )
const portfolioQuery = database.portfolioRef.where("docId", 'in', bookmarkIds);
portfolioQuery.onSnapshot((snapshot) => {
console.log(snapshot.docs)
if (snapshot.docs.length !== 0) {
var id = 1;
const tempItem = [];
snapshot.docs.forEach((doc) => {
tempItem.push({
id: id,
intervieweeName: doc.data().intervieweeName,
intervieweeEmail: doc.data().intervieweeEmail,
projectTitle: doc.data().projectTitle,
portfolioTitle: doc.data().portfolioTitle,
dateCreated: doc.data().dateCreated,
fbId: doc.id
})
id++;
})
setPortfolioData(tempItem)
}
})
}
useEffect(() => {
const getUserData = database.usersRef.where("email", "==", currentUser.email);
const bookmarkArray = [];
const unsub = getUserData.onSnapshot((snapshot) => {
snapshot.docs.forEach((doc) =>{
bookmarkArray.push(doc.data().bookmarkIds);
})
console.log(bookmarkArray);
getData(bookmarkArray)
})
return unsub;
}, [currentUser.email]);
Based on my current code above, I am receiving the following (Not getting any error just a blank return):
I realised I made a double array by doing
bookmarkArray.push(doc.data().bookmarkIds);
solved by doing
bookmarkArray = doc.data().bookmarkIds;
I want to add the addItem to the cartItems list, but if the id is the same as the item that already in the cartItems, I don't want to add another object, instead it will add the previous amountPrice and orderAmount with the new one.
Is there a way for me to achieve that?
const [cartItems, setCartItems] = useState(cartLocalStorage());
const addToCart = (id, name, image, amountPrice, orderAmount) => {
const addItem = {
id: id,
name: name,
image: image,
amountPrice: amountPrice,
orderAmount: orderAmount,
};
setCartItems([...cartItems, addItem]);
};
};
Give this a shot:
const addToCart = (id, name, image, amountPrice, orderAmount) => {
if(cartItems.find(i => i.id === id)){
setCartItems(cartItems.map(item => {
if(item.id === id){
item.amountPrice += amountPrice;
item.orderAmount += orderAmount;
}
return item;
}));
}else{
setCartItems([...cartItems, {id, name, image, amountPrice, orderAmount}]);
}
}
addToCart will check if the item is already in cartItems by id and if so, will add the values of amountPrice and orderAmount to the corresponding values of the existing element.
If, however, the id is not in cartItems, it will add a new element to the array.
I have not tested it and will probably not work but hopefully will set you in the right direction:
const [cartItems, setCartItems] = useState(cartLocalStorage());
const addToCart = (id, name, image, amountPrice, orderAmount) => {
const addItem = {
id: id,
name: name,
image: image,
amountPrice: amountPrice,
orderAmount: orderAmount,
};
const index = cartItems.findIndex(item => item.id === id);
if (index !== -1) {
cartItems[index] = {...cartItems[index], ...addItem};
setCartItems(cartItems);
} else {
setCartItems([...cartItems, addItem]);
}
};
Cheers
I'm trying to get the id from the element and then update it's state to the new id value.
The function where I handle the update:
updateID = (e) => {
console.log("IDFEEDING::" + this.state.id.feeding);
const { id, name } = e.target;
console.log("HereID::" + id + "," + name);
this.setState((prevState) => {
const updatedID = {
...prevState.id,
[name]: id
};
return {
id: updatedID
}
})
}
and here the element where I call the function to update the values. Update values works, but id no.. doesn't gives me erros, it's just doesn't update, I can't get the new id when I select a new radio button.
<RadioGroup id={this.state.id.feeding} aria-label="quiz" name="feeding" value={this.state.group.feeding}
onChange={(event) => {
var group = { ...this.state.group };
group.feeding = event.target.value;
this.setState({ group });
this.updateTotal(event)
var id = { ...this.state.id };
id.feeding = event.target.id;
this.setState({ id });
this.updateID(event)
}}>
Thanks in advance :)
setState is async, so it won't update the value immediately. You would need to make use of callback approach.
Also since you are executing many things within the onClick handler, I recommend you take it out into new function
updateID = ({ id, name }) => {
console.log("IDFEEDING::" + this.state.id.feeding);
console.log("HereID::" + id + "," + name);
this.setState((prevState) => {
const updatedID = {
...prevState.id,
[name]: id
};
return {
id: updatedID
}
})
}
onChange= (event) => {
var group = { ...this.state.group };
const {id, value, name } = event.target;
group.feeding = value;
var id = { ...this.state.id };
id.feeding = id;
// Use one setState instance to update both
this.setState({ id, group }, () => {
// using on callback
this.updateTotal(group);
this.updateID({id, name})
});
}
}
...
<RadioGroup id={this.state.id.feeding} aria-label="quiz" name="feeding" value={this.state.group.feeding}
onChange={this.onChange}>