'My react-native's increment counter using useState suddenly stopped incrementing. None of the existing solutions I found worked
My app has a component that consists of three buttons(only two are relevant though.) Yesterday I discovered that my setanimalNumber(animalNumber + 1) has stopped working. Animal number no longer increments.
const AnimalButton = ({remove, animalz, addtoList}) => {
const [animalNumber, setanimalNumber] = useState(1)
return (
<View style={styles.buttonGrouptrue} >
<Button title={animalNumber + ' ' + animalz}
onPress={() => remove(animalz)}
buttonStyle={styles.button} titleStyle={{color: 'black'}}
/>
<View style={styles.directionalButtons}>
<TouchableOpacity
onPress={() => {
setanimalNumber(animalNumber, animalNumber + 1)
addtoList([animalz, animalNumber + 1])
}}
style={styles.arrowButton}
>
<Image
style={{
marginLeft: 'auto',
marginRight: 'auto'
}}
source={require('../assets/arrow_up.png')}
></Image>
</TouchableOpacity>
</View>
</View>
);
}
I have looked around throughout stack overflow and I have tried the following options.
setanimalNumber(animalNumber => animalNumber + 1)
setanimalNumber(animalNumber++)
setanimalNumber(animalnNumber, animalNumber + 1)
const test = (value) => {
let newValue = value + 1
setanimalNumber(newValue)
}
I know this is a common issue, but none of the solutions I found seemed to work. Any advice at all would be appreciated.
Solution 1:[1]
Issue
Of the following implementations, two are correct, and two are incorrect.
Incorrect
setAnimalNumber(animalNumber, animalNumber + 1)The
useStatestate updater function takes only a single argument, either the value to update the state to or a callback function. This implementation only sets the state to the current value and ignores the second argument.setAnimalNumber(animalNumber++)This version will technically update the state value, but it mutated the state and won't trigger a rerender to see the new value.
Correct
-
const test = (value) => { let newValue = value + 1; setAnimalNumber(newValue); }This version will update the state, but doesn't take into account multiple enqueued state updates.
Example:
const [animalNumber, setAnimalNumber] = useState(1); ... test(animalNumber); // 1 + 1 -> 2 test(animalNumber); // 1 + 1 -> 2 test(animalNumber); // 1 + 1 -> 2The result of invoking
test(animalNumber);three times is that onlywas added to theanimalNumber` state. setAnimalNumber(animalNumber => animalNumber + 1)This is the correct way to enqueue a state update that depends on the value of the previous state.
setAnimalNumber(animalNumber => animalNumber + 1); // 1 + 1 -> 2 setAnimalNumber(animalNumber => animalNumber + 1); // 2 + 1 -> 3 setAnimalNumber(animalNumber => animalNumber + 1); // 3 + 1 -> 4The result of invoking
setAnimalNumber(animalNumber => animalNumber + 1);three times is that the previous state's value is used for each update.See Functional Updates.
Solution
const AnimalButton = ({ remove, animalz, addtoList }) => {
const [animalNumber, setAnimalNumber] = useState(1);
return (
<View style={styles.buttonGrouptrue}>
<Button
title={animalNumber + ' ' + animalz}
onPress={() => remove(animalz)}
buttonStyle={styles.button}
titleStyle={{ color: 'black' }}
/>
<View style={styles.directionalButtons}>
<TouchableOpacity
onPress={() => {
setAnimalNumber(number => number + 1); // <-- functional state update
addtoList([animalz, animalNumber + 1]);
}}
style={styles.arrowButton}
>
<Image
style={{
marginLeft: 'auto',
marginRight: 'auto'
}}
source={require('../assets/arrow_up.png')}
/>
</TouchableOpacity>
</View>
</View>
);
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Drew Reese |
