Reputation: 19
I had this problem for a while and can't find a solution.
I'm trying to change the state to complex data.
const [state, setState] = useState(null)
function Save(){
if(state){
setState((prev)=>[...prev, [p1, p2, p3, p4]])
}else{
setState([[p1, p2, p3, p4]])
}
}
First when I call the Save()
function the state is changed correctly
Array [
Array [
1,
2,
3,
4
],
]
But at the second run, I get the same state
Array [
Array [
1,
2,
3,
4
],
]
After that everything works correctly fine and the state is added
Array [
Array [
1,
2,
3,
4
],
Array [
5,
6,
7,
8
],
....
]
here is the full code
export default function ModalForm({close}) {
const { state, setState } = useStateContext()
const [name, setName] = useState('')
const [p1, setP1] = useState('')
const [p2, setP2] = useState('')
const [p3, setP3] = useState('')
const [p4, setP4] = useState('')
const [v1, setV1] = useState('')
const [v2, setV2] = useState('')
const [v3, setV3] = useState('')
const [v4, setV4] = useState('')
const [v5, setV5] = useState('')
async function Save(){
setState((prev) => {
if (prev) {
let id = state.length
return([...prev, [name, id, p1, p2, p3, p4, v1, v2, v3, v4, v5]])
} else {
return([[name, 0, p1, p2, p3, p4, v1, v2, v3, v4, v5]])
}
})
}
return (
<Pressable style={styles.centeredView} onPress={() => close()}>
<ScrollView>
<Pressable style={styles.modalView} onPress={() => console.log('hi')}>
<Text style={styles.modalText}>Make new!</Text>
<TextInput
textAlign='center'
style={styles.textInput}
onChangeText={text => setName(text)}
value={name}
placeholder="Name"
/>
<TextInput
textAlign='center'
style={styles.textInput}
keyboardType = 'numeric'
onChangeText={text => setP1(text)}
value={p1}
placeholder="Period 1"
/>
<TextInput
textAlign='center'
style={styles.textInput}
keyboardType = 'numeric'
onChangeText={text => setP2(text)}
value={p2}
placeholder="Period 2"
/>
<TextInput
textAlign='center'
style={styles.textInput}
keyboardType = 'numeric'
onChangeText={text => setP3(text)}
value={p3}
placeholder="Period 3"
/>
<TextInput
textAlign='center'
style={styles.textInput}
keyboardType = 'numeric'
onChangeText={text => setP4(text)}
value={p4}
placeholder="Period 4"
/>
<TextInput
textAlign='center'
style={styles.textInput}
keyboardType = 'numeric'
onChangeText={text => setV1(text)}
value={v1}
placeholder="Voltage 1"
/>
<TextInput
textAlign='center'
style={styles.textInput}
keyboardType = 'numeric'
onChangeText={text => setV2(text)}
value={v2}
placeholder="Voltage 2"
/>
<TextInput
textAlign='center'
style={styles.textInput}
keyboardType = 'numeric'
onChangeText={text => setV3(text)}
value={v3}
placeholder="Voltage 3"
/>
<TextInput
textAlign='center'
style={styles.textInput}
keyboardType = 'numeric'
onChangeText={text => setV4(text)}
value={v4}
placeholder="Voltage 4"
/>
<TextInput
textAlign='center'
style={styles.textInput}
keyboardType = 'numeric'
onChangeText={text => setV5(text)}
value={v5}
placeholder="Voltage 5"
/>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={() => {
Save()
close()
}}>
<Text style={styles.textStyle}>Save</Text>
</Pressable>
</Pressable>
</ScrollView>
</Pressable>
)
}
and the state is displayed in a flat List who looks like this:
<FlatList
data={state}
renderItem={Item}
keyExtractor={item => item[1]}
ListEmptyComponent={Empty}
styles={styles.container}
/>
added the change from the first answer
Upvotes: 1
Views: 1794
Reputation: 146
Whenever you use the previous state to evaluate what the new state will be, you should wrap it in the functional state update form, which passes the previous state as the first parameter to the function. Use that parameter, NOT the current state, to evaluate whatever you need to evaluate that relies on the current state. In your example, you need to make the following change:
function Save() {
setState((prev) => {
if (prev) {
return [...prev, [p1, p2, p3, p4]]
} else {
return [[p1, p2, p3, p4]]
}
}
}
Upvotes: 1