I have a few screens in my React Native app where I want to receive some user input, but on these screens I also want to start with initial values in the fields when the user first comes to visit the screen, especially if they are updating existing data. I can't see how to do this, because the moment I provide a default value the inputs seem to cease to be editable. On Picker
controls, they automatically reset themselves to the original value, on TextInput
fields they reset themselves to default after a momentary blink.
In the event handlers I can see the changed value being received but that data is not passed back to the dropdown, even though the default values are configured to reference the same object that I am updating in the event handler.
This code reproduces the problem I am seeing:
import {Picker} from '@react-native-picker/picker';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default function App() {
const scores = {
positive: 1,
negative: 2
};
const setScore = function(direction, scoreText) {
console.log("Set "+direction+" to "+score+" currently: "+JSON.stringify(scores));
let score = parseInt(scoreText);
if ( direction == 'positive' ) {
scores.positive = score;
} else {
scores.negative = score;
}
}
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
Select a different option in this dropdown and watch in astonishment as nothing happens!
</Text>
<Picker
onValueChange = { (itemValue, itemIdx) => setScore('positive', itemValue)}
selectedValue={scores.positive}
>
<Picker.Item key="1-0" label="0" value="0" />
<Picker.Item key="1-1" label="1" value="1" />
<Picker.Item key="1-2" label="2" value="2" />
<Picker.Item key="1-3" label="3" value="3" />
<Picker.Item key="1-4" label="4" value="4" />
</Picker>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});
This is visible in a working Snack here.
I can't see this problem showing up elsewhere so it is probably a fundamental misunderstanding on my part about how the React Native Input system is supposed to operate. How can I use Input fields to receive input from my users while having a default value selected when the screen is first loaded?
You have to use useState hook to track values mutable by user, as well as any dynamically changing values inside functional components. So instead of declaring scores as
const scores = {
positive: 1,
negative: 2
};
we can use useState hook
import React, { useState } from 'react'
...
const [scores, setScores] = React.useState({
positive: 1,
negative: 2
})
You declare them with initial values, and it returns the current state and setScores function that updates the state, so you can then set your state as
if ( direction == 'positive' ) {
setScores({positive: score})
} else {
setScores({negative: score})
}