React Native - Form Field Validation: Unable to cr

2019-08-27 17:19发布

问题:

I'm building a pin validation in the registration form to check if the first pin matches the second one. I created a validatePinConfirmation function that checks whether pin is equal to pin_confirmation. If it is then we set the state of pin_confirmation to the value inserted by the user. For some reason, the function or the form is not passing the value through and saving it to the DB. I would really appreciate if someone could point what I'm doing wrong exactly.

import React, { Component } from 'react';
import { View, AsyncStorage } from 'react-native';
import { Form, Item, Input, Label, Button, Text } from 'native-base';
import axios from 'axios';
import { JWT } from 'App';

class RegistrationForm extends Component {
	constructor(props) {
		super(props);
		this.state = {
			name: '',
			email: '',
			emailValidate: '',
			pin: '',
			pinValidate: '',
			role: 'Consumer',
			pin_confirmation: ''
		};
	}

	validateEmail(text, type) {
		alph = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/g;
		if (type == 'email') {
			if (alph.test(text)) {
				this.setState({ emailValidate: true });
			} else {
				this.setState({ emailValidate: false });
			}
		}
		if ({ emailValidate: true }) {
			this.setState({ email: text });
		}
	}

	validatePinConfirmation(text) {
		const { pin, pin_confirmation } = this.state;
		if (text == pin) {
			this.setState({ pinValidate: true });
		} else {
			this.setState({ pinValidate: false });
		}
		if ({ pinValidate: true }) {
			this.setState({ pin_confirmation });
		}
	}

	onSubmit = () => {
		const { name, email, pin, role, pin_confirmation } = this.state;
		axios
			.post('http://0.0.0.0:4000/api/v1/sign_up', {
				user: {
					name,
					email,
					pin,
					role,
					pin_confirmation
				}
			})
			.then(response => {
				AsyncStorage.setItem('JWT', response.data.jwt);
				console.log(response.data.jwt);
				this.props.navigation.navigate('Profile');
			})
			.catch(error => {
				console.log(error);
			});
	};

	render() {
		return (
			<View>
				<Form>
					<Item floatingLabel>
						<Label>Name</Label>
						<Input
							value={this.state.name}
							onChangeText={name => {
								this.setState({ name });
							}}
						/>
					</Item>
					<Item floatingLabel last>
						<Label>Email</Label>
						<Input
							autoCapitalize="none"
							value={this.state.email}
							onChangeText={text => this.validateEmail(text, 'email')}
						/>
					</Item>
					<Item floatingLabel last>
						<Label>Pin</Label>
						<Input
							keyboardType={'number-pad'}
							secureTextEntry
							value={this.state.pin}
							onChangeText={pin => {
								this.setState({ pin });
							}}
						/>
					</Item>
					<Item floatingLabel last>
						<Label>Pin Confirmation</Label>
						<Input
							keyboardType={'number-pad'}
							secureTextEntry
							value={this.state.pin_confirmation}
							onChangeText={text => this.validatePinConfirmation(text)}
						/>
					</Item>
				</Form>
				<Button onPress={this.onSubmit}>
					<Text> Submit</Text>
				</Button>
			</View>
		);
	}
}

export default RegistrationForm;

回答1:

Try the following:

<Input
    keyboardType={'number-pad'}
    secureTextEntry
    value={this.state.pin_confirmation}
    onChangeText={this.validatePinConfirmation.bind(this)}
/>

The context of this is out of the scope you want to use. Let me know if that works. You might have to do the same for onSubmit as well.



回答2:

this inside function created with function keyword is undefined & that's the issue you face you have two options

  1. use .bind() function this.validatePinConfirmation.bind(this)
  2. use arrow function for example validatePinConfirmation should be defined as flow

    validatePinConfirmation = (text) => { /* your code */} // this here isn't undefined since arrow function retains the value of the enclosing lexical context's this

you can get more about this from this blog post



回答3:

Alongside other suggestions fix your check

if ({ emailValidate: true }) {

this always be executed since any object is converted to boolean value of true. I believe you need to check for something like

if (this.state.emailValidate) {

but this actually will not work because .setState() is async operation. That is: calling .setState does not change state immediately. So you better introduce interm variable and check it:

let isEmailValid = true;
...
this.setState({emailValidate: isEmailValid});
if (isEmailValid) {
    this.setState({email: text});