React Native Form Validation

Viewed 43523

I created a login form using react-native and I want to validate every fields but I don't know how to do it. I'm quite new to react-native so I want to ask anyone for help. Form validation should show error under following conditions:

  • Input form is empty
  • Email text isn't email form.
  • Password text does not satisfy the conditions above.
  • If Input form has errors the login button should be disabled.
  • If Input form doesn't have any errors, show alert to inform login success

Sample image validation:

Sample image validation:

Here is my code:

import React from 'react';
import { StyleSheet, Text, View, Image, TextInput, Dimensions, ScrollView, 
CheckBox, TouchableOpacity } from 'react-native';
import logo from './image/Logo.png'

const { width: WIDTH } = Dimensions.get('window')

export default class App extends React.Component {
  constructor(){
    super();
    this.state={
      check:false,
      email: '',
    };
    this.validates = this.validates.bind(this);
  }

  CheckBoxText(){
      this.setState({
        check:!this.state.check,
      })
  }


  validates = () => { 

    let text = this.state.email; 
    let emailError = this.state.emails;
    let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ ; 
    if(reg.test(text) === false) 
    { 
    console.warn("Invalid email")
    this.setState({email:text}) 
    return false; 
    } 
    else { 
    this.setState({email:text}) 
    console.log("Email is Correct"); 
    } 
} 

  render() {
    return (

  <View>
    <View style={styles.container}>
      <Image source={logo} style={styles.logo}/>
    </View>

    <View style = {styles.container2}>
      <Text style={styles.emailAdd}>
        Email
      </Text>
      <TextInput 
            onChangeText={(text) => this.setState({email:text})} 
            type='email'
            value={this.state.email} 
            keyboardType='email-address'
            style={styles.emailInput}
            placeholder={'Input Email Address'}
            underlineColorAndroid='transparent'/>

    </View>

    <View style = {styles.container3}>
      <Text style={styles.password}>
        Password
      </Text>
      <TextInput 
            style={styles.passwordInput}
            placeholder={'Input Password'}
            secureTextEntry={true}
            underlineColorAndroid='transparent'/>

    </View>

    <View style = {styles.container4}>

          <View>
            <CheckBox value={this.state.check} onChange={()=>this.CheckBoxText()} style={styles.rememberMe}/>
          </View>
          <View>
            <Text style={styles.remember}>Remember me</Text>
          </View>
    </View>

    <TouchableOpacity style={styles.btnLogin} onPress={this.validates} >
          <Text style={styles.txtLogin}>Sign In</Text>
    </TouchableOpacity>


  </View>

);
  }
}
2 Answers

I recommend using formik and yup to easily build a login form with input validation. These two packages when integrated together, simplifies your codebase thanks to both of its features.

Please take a look at a CodeSandbox snippet here, https://codesandbox.io/s/stack-overflow-54204827-llvkzc?file=/index.tsx:254-656. And note, I'm using typescript here.

The package.json file at the time of written snippet is:

  "dependencies": {
    ...
    "formik": "2.2.9",
    ...
    "yup": "0.32.11"
  },

And to break the solution down, first we define our yup schema for our Login form:

Note, you may tweak the regex pattern later, as this password validation accepts min 6 to max 12 characters, with at least one uppercase letter, one lowercase letter, one number and one special character.

/**
 * The `yup` Login Form schema
 */
const LoginSchemaA = Yup.object().shape({
  email: Yup.string()
    .email("Invalid email.")
    .required("Email must be provided."),
  password: Yup.string()
    .required("Password must be provided.")
    .matches(
      /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*])(?=.{6,12})/,
      "Password must be minimum 6 and maximum 12 characters."
    )
});

Note, .email("Invalid email.") here is the default email validation feature used. You can remove this, and use .matches(...) function instead for your own regular expression.

And just the <Formik /> section for your further use:

      <Formik
        initialValues={{
          email: "",
          password: ""
        }}
        validationSchema={LoginSchemaA}
        onSubmit={(
          values: Values,
          { setSubmitting }: FormikHelpers<Values>
        ) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            setSubmitting(false);
          }, 500);
        }}
      >
        {({ errors, touched }) => (
          <Form>
            <label htmlFor="email">Email</label>
            <Field
              id="email"
              name="email"
              placeholder="john.doe@email.com"
              type="email"
            />
            {errors.email && touched.email ? (
              <div style={{ color: "red" }}>{errors.email}</div>
            ) : null}

            <label htmlFor="password">Password</label>
            <Field id="password" name="password" type="password" />
            {errors.password && touched.password ? (
              <div style={{ color: "red" }}>{errors.password}</div>
            ) : null}

            <button type="submit">Submit</button>
          </Form>
        )}
      </Formik>

Lastly, you would want to grab the values itself for further use - ignore the setTimeout, alert and setSubmitting usages.

An example output of JSON.stringify(values, null, 2) would be as below:

{
  "email": "john.doe@test.com",
  "password": "Awesome@Password!2022"
}

Hope this helps you in your react-native coding journey!

here is my code you can try this

import React, { Component } from "react"
import { View, Button } from "react-native"

import TextField from "textfield"
import validation from "validation"
import validate from "validation_wrapper"

export default class Form extends Component {
  constructor(props) {
    super(props)

    this.state = {
      email: "",
      emailError: "",
      password: "",
      passwordError: ""
    }
  }

  register() {
    const emailError = validate("email", this.state.email)
    const passwordError = validate("password", this.state.password)

    this.setState({
      emailError: emailError,
      passwordError: passwordError
    })

    if (!emailError && !passwordError) {
      alert("Details are valid!")
    }
  }

  render() {
    return (
      <View>
        <TextField
          onChangeText={(value) => this.setState({ email: value.trim() })}
          onBlur={() => {
            this.setState({
              emailError: validate("email", this.state.email)
            })
          }}
          error={this.state.emailError}
        />

        <TextField
          onChangeText={(value) => this.setState({ password: value.trim() })}
          onBlur={() => {
            this.setState({
              passwordError: validate("password", this.state.password)
            })
          }}
          error={this.state.passwordError}
          secureTextEntry={true}
        />

        <Button title="Register" onPress={this.validateRegister} />
      </View>
    )
  }
}

<!-- begin snippet: js hide: false console: true babel: false -->

const validation = {
  email: {
    presence: {
      message: "^Please enter an email address"
    },
    email: {
      message: "^Please enter a valid email address"
    }
  },

  password: {
    presence: {
      message: "^Please enter a password"
    },
    length: {
      minimum: 5,
      message: "^Your password must be at least 5 characters"
    }
  }
}

export default validation

import validation from "validation.js"

export default function validate(fieldName, value) {
  // Validate.js validates your values as an object
  // e.g. var form = {email: 'email@example.com'}
  // Line 8-9 creates an object based on the field name and field value
  var formValues = {}
  formValues[fieldName] = value

  // Line 13-14 creates an temporary form with the validation fields
  // e.g. var formFields = {
  //                        email: {
  //                         presence: {
  //                          message: 'Email is blank'
  //                         }
  //                       }
  var formFields = {}
  formFields[fieldName] = validation[field]

  // The formValues and validated against the formFields
  // the variable result hold the error messages of the field
  const result = validatejs(formValues, formFields)

  // If there is an error message, return it!
  if (result) {
    // Return only the field error message if there are multiple
    return result[field][0]
  }

  return null
}

import React from "react"
import { View, TextInput, Text } from "react-native"

const TextField = (props) => (
  <View>
    <TextInput />
    props.error ? <Text>{props.error}</Text> : null
  </View>
)

export default TextField
Related