Im trying to put together a simple counter which changes the quantity of an item. Using Hooks to manage its state, i update the value on screen correctly. However, the value the state holds when i console log is always one less than the value on the screen.
For example:
If starting value is 1, after pressing the plus button, the value on screen changes to 2 but in console the state value is still 1.
Setup of Hooks and functions controlling the count:
//Set Quantity
const [quantity, setQuantity] = useState(1);
//Set Item price
const [itemPrice, setItemPrice] = useState(itemOptions[0].price)
//Counter Control
const [disableMinus, setDisableMinus] = useState(true);
const addQuantity = () => {
if (quantity === 1) {
setQuantity(quantity 1);
setDisableMinus(false);
console.log(quantity)
} else {
if (quantity > 1){
setQuantity(quantity 1);
setDisableMinus(false);
console.log(quantity)
}
}
}
const minusQuantity = () => {
if (quantity === 1){
setDisableMinus(true);
} else {
if (quantity > 1) {
setQuantity(quantity - 1);
setDisableMinus(false);
console.log(quantity)
}
}
}
return (
<View style={{flexDirection: 'row', alignItems: 'center', justifyContent: "center", paddingVertical: 20}}>
<TouchableOpacity disabled={disableMinus} onPress={() => minusQuantity()}>
<AntDesign style={{color: '#37BD6B'}} name="minuscircle" size={30}/>
</TouchableOpacity>
<Text style={{paddingHorizontal: 10, fontWeight: '700', fontSize: 30}}>{quantity}</Text>
<TouchableOpacity onPress={() => addQuantity()}>
<AntDesign style={{color: '#37BD6B'}} name="pluscircle" size={30}/>
</TouchableOpacity>
)
Thanks in advance
CodePudding user response:
Setters from useState
are async.
You could log it this way
useEffect(()=>{
console.log(quantity)
}, [quantity]
This means: when dependency [quantity]
change, execute the function
passed as first param
To avoid stale closure (happening when 2 fast clicks or rand randers), you should use setters and passing it a function instead of the "current" value:
setQuantity(prevQuantity => prevQuantity 1);
CodePudding user response:
Here is another way you might set things up:
const addQuantity = () => {
...
setQuantity(oldQuantity => {
const newQuantity = oldQuantity 1
console.log(newQuantity) // console.log moved here. Also could be console.log("Incremented quantity to:", quantity)
return newQantity
});
...
}
This approach would allow you to log the new quantity value beore it is set. In this approach, you can perform a specific action (in this case console.log) on a case by case basis.
On the other hand, the useEffect
approach in @Poptocrack's answer will track all changes to the quantity
state. It has significantly less code and could be more desirable depending on your needs.
Hope you find one that fits your needs best from the two approaches.