how can i get the value of this inputs in react native? - javascript

so i cannot manage to get the value of any of my inputs, and the only thing is working for me is grabbing them inside render but just getting letter by letter. I want to use the same state for all of them (formData) so when I submit I can grab all the values in an unique object
Any recommendation to solve it??
export default class TimeOff extends Component {
constructor(props) {
super(props);
this.state = {
selectedStartDate: null,
selectedEndDate: null,
selectedValue: '',
formData: '',
};
}
handleSubmit = event => {
event.preventDefault()
console.log(this.state.formData)
render(){
Moment.locale('en')
const { selectedStartDate, selectedEndDate, formData, selectedValue } = this.state;
const minDate = new Date();
const maxDate = new Date(2090, 1, 1);
const startDate = selectedStartDate ? selectedStartDate.toString() : '';
const endDate = selectedEndDate ? selectedEndDate.toString() : '';
return(
<ScrollView showsVerticalScrollIndicator={false}>
<Navbar />
<Text style={styles.hOneTimeOff}>Schedule time off</Text>
<View style={styles.timeOffWrapper}>
<TextInput
name="firstname"
style={styles.timeOffInput}
mode='outlined'
placeholder="First name"
value={formData.firstname}
onChangeText={firstname => this.setState({formData: firstname})}
/>
<TextInput
name="lastname"
style={styles.timeOffInput}
mode='outlined'
placeholder="Last name"
value={formData.lastname}
onChangeText={lastname => this.setState({formData: lastname})}
/>
<Picker
name="role"
style={styles.timeOffPicker}
value={formData.role}
selectedValue={selectedValue}
onValueChange={role => this.handlePicker(role)}
>
<Picker.Item label="What's your role?" value=''/>
<Picker.Item label='Warehouse' value='Warehouse'/>
<Picker.Item label='Bakery' value='Bakery'/>
<Picker.Item label='Dry pack' value='Dry pack'/>
<Picker.Item label='Dry mix' value='Dry mix'/>
<Picker.Item label='Maintenance' value='Maintenance'/>
<Picker.Item label='Mechanical' value='Mechanical'/>
</Picker>
<View style={styles.container}>
<CalendarPicker
startFromMonday={true}
allowRangeSelection={true}
minDate={minDate}
maxDate={maxDate}
selectedDayColor="#00486D"
selectedDayTextColor="#FFFFFF"
/>
<View>
<Text>Start Date: {Moment(startDate).format("M/D/YYYY")}</Text>
<Text>End Date: {Moment(endDate).format("M/D/YYYY")}</Text>
</View>
</View>
<TouchableOpacity style={styles.btnTimeOff} onPress={this.handleSubmit}>
<Text style={styles.btnTextTimeOff}>Submit</Text>
</TouchableOpacity>
</View>
</ScrollView>
)
}
}

Your on change function is always overwriting your entire previous state.
You can use the setState function with a callback and the spread operator to update the state without losing previous state like so:
First create and function for onTextChange:
const handleChange = (name, value) => {
this.setState(
(previousState) => {
let previousFormData = previousState.formData;
return {
...previousState,
formData: {
...previousFormData,
[name]: value
}
}
}
)
}
Then Update you component like so:
export default class TimeOff extends Component {
constructor(props) {
super(props);
this.state = {
selectedStartDate: null,
selectedEndDate: null,
selectedValue: '',
formData: '',
};
}
handleSubmit = event => {
event.preventDefault()
console.log(this.state.formData)
}
handleChange = (name, value) => {
this.setState(
(previousState) => {
let previousFormData = previousState.formData;
return {
...previousState,
formData: {
...previousFormData,
[name]: value
}
}
}
)
}
render(){
Moment.locale('en')
const { selectedStartDate, selectedEndDate, formData, selectedValue } = this.state;
const minDate = new Date();
const maxDate = new Date(2090, 1, 1);
const startDate = selectedStartDate ? selectedStartDate.toString() : '';
const endDate = selectedEndDate ? selectedEndDate.toString() : '';
return(
<ScrollView showsVerticalScrollIndicator={false}>
<Navbar />
<Text style={styles.hOneTimeOff}>Schedule time off</Text>
<View style={styles.timeOffWrapper}>
<TextInput
name="firstname"
style={styles.timeOffInput}
mode='outlined'
placeholder="First name"
value={formData.firstname}
onChangeText={text => this.handleChange("firstname", text)}
/>
<TextInput
name="lastname"
style={styles.timeOffInput}
mode='outlined'
placeholder="Last name"
value={formData.lastname}
onChangeText={text => this.handleChange("lastname", text)}
/>
<Picker
name="role"
style={styles.timeOffPicker}
value={formData.role}
selectedValue={selectedValue}
onValueChange={role => this.handlePicker(role)}
>
<Picker.Item label="What's your role?" value=''/>
<Picker.Item label='Warehouse' value='Warehouse'/>
<Picker.Item label='Bakery' value='Bakery'/>
<Picker.Item label='Dry pack' value='Dry pack'/>
<Picker.Item label='Dry mix' value='Dry mix'/>
<Picker.Item label='Maintenance' value='Maintenance'/>
<Picker.Item label='Mechanical' value='Mechanical'/>
</Picker>
<View style={styles.container}>
<CalendarPicker
startFromMonday={true}
allowRangeSelection={true}
minDate={minDate}
maxDate={maxDate}
selectedDayColor="#00486D"
selectedDayTextColor="#FFFFFF"
/>
<View>
<Text>Start Date: {Moment(startDate).format("M/D/YYYY")}</Text>
<Text>End Date: {Moment(endDate).format("M/D/YYYY")}</Text>
</View>
</View>
<TouchableOpacity style={styles.btnTimeOff} onPress={this.handleSubmit}>
<Text style={styles.btnTextTimeOff}>Submit</Text>
</TouchableOpacity>
</View>
</ScrollView>
)
}
This also preserves the other variables in your state object.

You keep overwriting the "formData" state value.
Since you want it to act as an object (with entries: "firstname", "Lastname", etc) when you setState you should wrap the entries with curly brackets like this:
...
onChangeText={firstname => this.setState({formData: {firstname}})}
...
onChangeText={lastname=> this.setState({formData: {lastname}})}
...

onChangeText={firstname => this.setState({formData: {...this.state.formData, firstname}})}
onChangeText={lastname=> this.setState({formData: {...this.state.formData, lastname}})}
Use this to update the nested state object, it will keep old values and would also update new one

Related

Updating flatList in two different components

So I have Task, and task are created in a new component. They simply add the information to the array that stores all of the tasks.
I tried creating a global boolean called refresh(I know global isn't best practice, I just need to get this working, I don't mind about best practice right now). Then I set extradata = {global.refresh} and I set global.refresh = true every time the page is opened, but it doesn't do anything.
I could really appreciate someone to tell me what i'm doing wrong.
function HomeScreen({ navigation }) {
global.refresh = false;
const [selectedId, setSelectedId] = useState(null);
var currentDate = new Date();
var formatedDate = moment(new Date()).format("YYYY-MM-DD")
console.log(formatedDate)
var one = {
name:'Dishwasher',
task:"Clean",
time:formatedDate}
var two = {
name:'Fishwasher',
task:'<lean',
time:formatedDate
}
global.obj = [
one,
two,
]
return (
<View>
<Button
title="New Task"
accessibilityLabel="Create a new Task"
onPress={() =>
{
navigation.navigate('NewTask')
}}
/>
<FlatList
data = {obj}
extraData={global.refresh}
renderItem={({ item }) =>
<View>
<Task
name={item.name}
description={item.task}
time={item.time}/>
</View>
}/>
<StatusBar style="auto" />
</View>
)
}
In my newTask component, I simply add to the obj array and I set global.refresh = !global.refresh.
class NewTask extends Component {
state = {
item: 'Car',
name:'',
};
updateItem = (item) => {
this.setState({item: item})
}
updateName = (name) => {
this.setState({name: name})
}
render() {
return (
<View>
<Picker
selectedValue={this.state.item}
onValueChange={this.updateItem}>
<Picker.Item label="Car" value="Car" />
<Picker.Item label="HVAC Unit" value="HVAC" />
<Picker.Item label="Fridge" value="Fridge" />
<Picker.Item label="Smoke Detector" value="Smoke" />
<Picker.Item label="Dryer" value="Dryer" />
<Picker.Item label="Water Heater" value="water" />
</Picker>
<TextInput
placeholder = "Name: "
label='Name: '
value={this.state.name}
onChangeText={this.updateName}>
</TextInput>
<Button
title = "Create Task"
onPress={() => {
//Adds data - removed for sake of space.
}
this.props.navigation.navigate('Home')}
}
>
</Button>
</View>
);
}
}
Please if someone could help me that would be amazing. I've been stuck at this for so long. I've tried to read docs but it doesn't make sense to me with it being in two different components. I know I'm supposed to use this.state but I don't get how.
I don't need the best solution, just a solution.

Calling an Input in onPress

I am trying to call my emailInput and have it show up on my createPassword page, specifically where youremail#email.com is. I have given the two pages below, the email page consisting of a user input and the password page where I want that user input to appear on. I cannot really wrap my head around how to refer to the Input in my onPress. Any insight at all is appreciated more than you know!
Also, can I call two onPress's like that? Or do I need to create two functions and do it that way?
SignUpEmail.js
export default class SignUpEmailPage extends Component {
constructor() {
super();
this.state = {
color1: '#A2A2A2'};}
render() {
return (
<View style={styles.containerMain}>
{/* Email Input */}
<Container style = {styles.emailInput}>
<Form>
<Item floatingLabel >
<Label style={{color:this.state.color1}}>Email Address</Label>
<Input
style={styles.textInput}
autoCorrect={false}
autoCapitalize="none"
onFocus={() => this.setState({color1: '#F7018D'})}
onBlur={() => this.setState({color1: '#A2A2A2'})}
/>
</Item>
</Form>
</Container>
<View style={styles.containerBottom}>
<ContinueButton
onPress = {() => navigation.navigate('CreatePassword', { emailInput: })}
onPress={() => this.props.navigation.navigate('CreatePassword')}
/>
</View>
CreatePassword.js
export default class CreatePasswordPage extends Component {
constructor() {
super();
this.state = {
color1: '#A2A2A2'};}
render() {
return (
<View style={styles.containerMain}>
{/* Password Input */}
<Container style = {styles.passwordInput}>
<Form>
<Item floatingLabel>
<Label style={{color:this.state.color1}}>Password</Label>
<Input
style={styles.textInput}
autoCorrect={false}
autoCapitalize="none"
secureTextEntry={true}
onFocus={() => this.setState({color1: '#F7018D'})}
onBlur={() => this.setState({color1: '#A2A2A2'})}
/>
</Item>
</Form>
</Container>
<View style={styles.containerHeader}>
<Text style={styles.title}>Create a Password</Text>
</View>
<View style={styles.containerCaption}>
<Text style={styles.caption}> Lets create your Password for
</Text>
</View>
<View style={styles.containerCaption2}>
<Text style={styles.caption}> youremail#email.com</Text>
</View>
<View style= {styles.backArrowPlacement}>
<BackArrow
onPress={() => this.props.navigation.navigate('SignUpEmail')}
/>
</View>
<View style={styles.containerBottom}>
<ContinueButton
onPress={() => this.props.navigation.navigate('PhoneVerification')}
/>
</View>
</View>
);
}
}
You can't use navigation.navigate as it needs Hooks implementation in the functional component. You can do is
export default class SignUpEmailPage extends Component {
constructor() {
super();
this.state = {
color1: '#A2A2A2',
inputValue: '', // add state here
};
}
updateInputValue = (evt) => {
this.setState({
inputValue: evt.target.value
});
}
render() {
return (
<Input
value = {this.state.inputValue}
onChange={this.updateInputValue }
/>
<ContinueButton
//onPress = {() => navigation.navigate('CreatePassword', { emailInput: })} // remove this
onPress={() => this.props.navigation.navigate('CreatePassword',{ emailInput: this.state.inputValue })} // use this like
/>
)
}
}

how to acces to my checkbox component state?

Hi I am doing some kind of form in react native and i have this checkbox component that works fine, but i cant get his value on my form.js. I have the same problem with other components like datepicker. im unable to pass the values
any suggestion would be aprreciated
this is my checkbox component
import { CheckBox } from 'react-native-elements';
export default class CheckBoxs extends Component {
constructor() {
super();
this.state = {
checked1: true,
checked2: false,
};
}
render() {
return (
<View style={styles.checkbox} >
<CheckBox
containerStyle={styles.checkbox}
textStyle={styles.checkboxTxt}
uncheckedColor={'#b3b4b5'}
checkedColor={"#911830"}
key={1}
title="Mujer"
value={1}
value="1"
checkedIcon="stop"
checked={this.state.checked1}
onPress={() => this.setState({ checked1: !this.state.checked1, checked2: this.state.checked1 })}
/>
<CheckBox
containerStyle={styles.checkbox}
textStyle={styles.checkboxTxt}
uncheckedColor={'#b3b4b5'}
checkedColor={"#911830"}
key={0}
title="Hombre"
value={0}
value="0"
checkedIcon="stop"
checked={this.state.checked2}
onPress={() => this.setState({ checked2: !this.state.checked2, checked1: this.state.checked2 })}
/>
</View>
);
}
}
this is my form code
import CheckBoxs from './CheckBoxs';
const PersonalForm = ({onSubmit, errorMessage}) => {
import CheckBoxs from './CheckBoxs';
const PersonalForm = ({onSubmit, errorMessage}) => {
const [vName, setvName] = useState('');
const [vSecondName, setvSecondName] = useState('');
const [vLastName, setvLastName] = useState('');
const [vSecondLastName, setvSecondLastName] = useState('');
const [vCellphone, setvCellphone] = useState('');
const [vBirthDate, setvBirthDate] = useState('');
const [vRFC, setvRFC] = useState('');
const [vGender, setvGender] = useState('');
const [vEmail, setvEmail] = useState('');
const [checked] = useState('false');
return (
<ScrollView>
<View style={styles.buttonContainer}>
<View style={styles.inputContainer}>
<TextInput style={styles.inputs}
placeholder="Apellido materno"
onChangeText={newvSecondLastName => setvSecondLastName(newvSecondLastName)}
underlineColorAndroid='transparent'
value={vSecondLastName}
autoCorrect={false}
autoCapitalize='characters'
/>
</View>
<View>
<MyDatePicker />
</View>
<View style={styles.checkbox} >
<CheckBoxs />
</View>
<View style={styles.inputContainer}>
<TextInput style={styles.inputs}
placeholder="Correo electrónico"
underlineColorAndroid='transparent'
onChangeText={newvEmail => setvEmail(newvEmail)}
value={vEmail}
autoCorrect={false}
autoCapitalize='characters'
/>
</View>
</View>
<View style={styles.buttonContainer2}>
<TouchableOpacity
style={ styles.logout}
onPress={() => onSubmit(vName, vSecondName, vLastName, vSecondLastName, vCellphone, vBirthDate, vRFC, vGender, vEmail),console.log(vName, vSecondName, vLastName, vSecondLastName, vCellphone, vBirthDate, vRFC, vGender, vEmail)}
>
<Text style={styles.loginText}>GUARDAR</Text>
</TouchableOpacity>
</View>
</ScrollView>
);
};
Have your component accept an 'onChange' callback (via props), and invoke it with the new value, whenever the value changes.
For example:
<Parent>
<Kid onChange={ newValue => { /* use the new value... */ } }/>
</Parent
Or another example:
const Parent = () => (
<View>
<TwoCheckboxes
onChange={
newValues => console.log('parent got new values', newValues)
}
/>
</View>
);
const TwoCheckboxes = props => {
const [ values, setValues ] = useState([ true, false]);
const [ val1, val2 ] = values;
const updateValuesAndReportChange = (newValues) => {
setValues(newValues);
props.onChange(newValues); /** this will pass updated values to Parent */
};
return (
<View>
<Checkbox
onPress={ () => updateValuesAndReportChange([ !val1, val2 ]) }
/>
<Checkbox
onPress={ () => updateValuesAndReportChange([ val1, !val2 ]) }
/>
</View>
);
};
In the React Native Docs:
This is a controlled component that requires an onValueChange callback that updates the value prop in order for the component to reflect user actions. If the value prop is not updated, the component will continue to render the supplied value prop instead of the expected result of any user actions.
So, add onValueChange to your Checkbox component. Store the value that it gives you in the component state, and pass that state to Checkbox through its value property.
An Example:
<Checkbox onValueChange={value => /** update **/} value={/** stored value **/} ... />

How to pass value to placeholder to textInput in redux-form?

So I'm creating a login form with two fields, username & password respectively; and I would like to pass placeholder to each of these Field. however, no matter what I try, the placeholder is not shown.
Code
const submit = values => {
console.log('submitting form', values)
};
const renderInput = ({ input: { onChange, ...restInput } }) => {
return <TextInput style = { styles.input } onChangeText = { onChange } { ...restInput }/>
};
const LoginForm = props => { const { handleSubmit } = props;
return (
<View style={styles.container}>
<View>
<Field name="email" placeholder="Email" component={renderInput} />
<Field name="password" placeholder="Password" component={renderInput} />
</View>
<View>
<View style={styles.loginBtnContainer}>
<TouchableOpacity style={styles.button} onPress={handleSubmit(submit)}>
<Text style={{fontSize: 30, color: '#17a2e0'}}>Login</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
}
export default reduxForm({
form: 'test'
})(LoginForm)
As you can see, the two fields with name email & password respectively are not present in TextInput in renderInput function.
In your component renderInput in its props you will have available the ones applied to the component Field. As documentation states, you just have to apply the attribute placeholder in the TextInput component to get placeholder rendered.
const renderInput = ({ placeholder, input: { onChange, ...restInput } }) => {
return <TextInput placeholder={placeholder} style = { styles.input } onChangeText = { onChange } { ...restInput }/>
};

Render on TextInput Submit - React Native

In a a react native app I have some text and then a textinput rendered on the screen. I'm trying to figure out how to output the same text and the same textinput when I submit on in the original text field. I was thinking to do this recursively but I'm not sure how where and how implement the function to do so.
If it's in the same screen, than you can use local state. here's the example
class TestScreen extends Component {
constructor(props) {
super(props)
this. state = {
firstInput:'First Input',
secondInput:''
}
this.submit = this.submit.bind(this)
}
submit(){
this.setState({ secondInput: this.state.firstInput })
}
render() {
return (
<View style={{flex:1,marginTop:40}}>
<View>
<Text>Text Input #1</Text>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onChangeText={(text)=> this.setState({firstText:text})}
value={this.state.firstInput}
/>
<Button
onPress={this.submit}
title="Submit"
/>
</View>
<View style={{marginTop:20}}>
<Text>Text Input #1</Text>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
value={this.state.secondInput}
/>
</View>
</View>
);
}
}
I hope that help. Thanks
Perhap you can use ref,state,conditional rendering. let's code talk
const MyInputs = (props) => {
inputs =props.inputs
result=inputs.map(function(value,index){
return(
<TextInput key={index} style={styles.input} value={value} />
)
})
return(
<View>
{result}
</View>
)
}
class TestScreen extends Component {
constructor(props) {
super(props)
this. state = {
inputs:[]
}
this.submit = this.submit.bind(this)
this.clearText = this.clearText.bind(this)
}
submit(){
let lastInput=this._textInput._lastNativeText
let inputs=this.state.inputs
this._textInput.setNativeProps({text: ''});
inputs.push(lastInput)
this.setState({
inputs:inputs
})
}
clearText = () => {
this.setState({
inputCount: this.state.inputCount + 1,
})
this._textInput.setNativeProps({text: ''});
}
render() {
return (
<View style={{flex:1,marginTop:40}}>
<View>
<Text>Text Input #1</Text>
<TextInput
style={styles.input}
ref={component => this._textInput = component}
/>
<Button onPress={this.submit} title="Submit"
/>
</View>
<MyInputs inputs={this.state.inputs}/>
</View>
);
}
}

Categories