React – Material UI – Validate Email Input Field

Photo by Karolina Grabowska from Pexels

Overview

Validating user inputs is an essential aspect of any web application. It helps to ensure that data is entered correctly and reduces the likelihood of errors. This blog post will show you how to validate email with React and Material UI text fields. By combining the power of React and Material UI, you can easily create a text field for entering email addresses and validate the format of the entered data. In this tutorial, we will guide you through the process of using React and Material UI to validate the email and provide an alternative way to validate form fields.

For a more in depth post on React Field Validation with Formik and Yup, please check out these articles.

Source Files For This Article

URL: https://github.com/fullstacksoup/blog-react-email-input-validation-demo

Get Source Code

Prerequisite

Create a new React-App.

npx create-react-app my-app
cd my-app

React Material UI Version 4

Install the Material Core. and Validator libraries with Node Package Manager.

npm install @material-ui/core@4.12.3
npm install validator

npm start

Parent Form Class Component

Create a new class component labeled FormParent.js. Add the following imports and state variables. Grid is used to align the field and submit button.

import React, {Component} from 'react';
import Grid from '@material-ui/core/Grid';
import Button from '@material-ui/core/Button';
import InputEmailField from './InputEmailField';

export default class OfferSupportForm extends React.Component {

constructor(props) {
     super(props);
     this.state = {
         Email: '',
         IsValidEmail: false,
     };           
     this.handleEmailChange.bind(this);
}

Handle the email change and submit events.

handleEmailChange = (value, isValid) => {        
    this.setState({Email: value, isValidEmail: isValid});                                
}


handleSubmitForm = (event) => {        
  console.log('handleSubmitForm  ', event);
}

Render the Input Field and the Submit Button. Notice the submit button is disabled until IsValidEmail is equal to true. In the example below, the helperText, label, fieldName, and handleChange() event function is passed to the InputEmailField component.

 render() {
    return (                        
        <>            
            <Grid container spacing={1} style={{marginTop: '20px'}}>        
            
                <Grid sm={4} align="left"></Grid>
                
                <Grid sm={1} className="fieldLayoutMT15">                    
                    <InputEmailField    helperText="(Required)" 
                                        label="Email" 
                                        fieldName="Email" 
                                        handleChange={this.handleEmailChange} 
                                        />
                </Grid>

                <Grid sm={1} align="right">                    
                    {this.state.IsValidEmail === true ?
                        <Button variant="contained"  color="primary" onClick={this.handleSubmitForm}>                             
                            Submit
                        </Button>
                        :
                        <Button variant="contained"  color="primary" disabled>                             
                            Submit
                        </Button>
                    }                                                             
                </Grid>
                        
            </Grid>                                            
        </>
    );
}

Email Input Component

Create a new JavaScript file labeled InputEmailFIeld.js and import the following libraries.

import React, { useState } from 'react'
import TextField from '@material-ui/core/TextField';
import FormControl from '@material-ui/core/FormControl';
import isEmail from 'validator/lib/isEmail';

Input Validation

Create a function to handle the changes in the Input component. Use the validator’s IsEmail() method to validate the emails string. Send the value and a boolean for validation state to the parent component.

const handleChange = event => {
   const val = event.target.value;                
        
   if(isEmail(val)) {
      setIsValid(true);              
   } else {
      setIsValid(false);              
   }
        
   setValue(val);                
   props.handleChange(val, isValid);
}

In the function portion of the component set the email state and the change event handler. The handleChange() will count the number of digits 0-9 and if there are 10 digits set a boolean variable to true. Both the email address value and validation boolean variable are sent to the parent by props.handleEmailChange( val, isValid ).

export default function InputEmailField(props) {   
    const [value, setValue] = useState('');
    const [isValid, setIsValid] = useState(false);
    
    const handleChange = event => {
        const val = event.target.value;                
        
        if(isEmail(val)) {
            setIsValid(true);              
        } else {
            setIsValid(false);              
        }
        
        setValue(val);                
        props.handleChange(val, isValid);
    }

Render Input Field

The input field will render as an outlined field with the label embedded in the upper left using the InputLabelProps setting shrink to true.

    return (
        <React.Fragment>
            <FormControl fullWidth={props.isFullWidth} >
                <TextField         
                                     
                    onBlur={() => setDirty(true)}
                    id={props.fieldName}                    
                    label={props.label}
                    name={props.fieldName}                    
                    variant="outlined" 
                    size={'small'}
                    helperText={props.helperText}
                    value={value}
                    InputLabelProps={{
                      shrink: true,
                    }}
                    onChange={(e) => handleChange(e)}
                  
                />
                
            </FormControl>
        </React.Fragment>
    )

Material Field Error Property

In addition to disabling a Submit Button we can use the error property in Material <TextField /> which will show a red border input. Before showing an error when the form hasn’t been touched we can set another variable to track if the field is pristine or dirty. In the example below we just want to know is the field is dirty (has been modified by the user). Also we can contain the states inside the input component.

const [isValid, setIsValid] = useState(false)  
const [dirty, setDirty] = useState(false);

Error Handling

Using the error property to show a red border if the field does not have a valid email address.

error={dirty && !isValid}              

Using the onBlur() event, set the dirty to true. This means the user touched the field and went elsewhere on the form.

  <OutlinedInput                                     
    error={dirty && isValid === false}                                        
    onBlur={() => setDirty(true)}
    onChange={(e) => handleChange(e)}
    name={props.fieldName}
    label={props.label}
    size={'small'}          
    value={value}
    InputLabelProps={{
      shrink: true,
    }}    
  />

Validation With Formik

Formik with Yup are the most commonly used form validation library combo for react. The method above is easier to understand at first but in the end more code to maintain. Eventually, everyone uses Formik and Yup.

Formik & Yup validate the field and tracks the state whether it is pristine or dirty.

Please check out the following articles each with source files for a working example on GitHub.
React Form Validation with Formik & Yup Click Here.
React Stepper Form Validation with Formik & Yup Click Here.

Install Formik and Yup

Formik and Yup are used for form validation.

npm i formik
npm i yup

Yup Validation Schema

Import the following libraries

import { useFormik } from 'formik';
import * as yup from 'yup';

Create a validation schema with Yup, This will validate the email so it must resemble something like username@email.com without certain special characters in the username etc.

const validationSchema = yup.object({
 email: yup
      .string('Enter your email')
      .email('Enter a valid email')
      .required('Email is required'),    

});

Formik

Create a formik function with the useFormik() hook. The validationSchema defined with Yup will check if the input is valid and if it passes then submit the form.

const formik = useFormik({
    initialValues: {
      email: '',
    },
    validationSchema: validationSchema ,    
    onSubmit: values => {     
        // Handle Submit
    },
});

Masked Input

The input events and properties, onChange, helperText, error, and value are handled by formik.

<TextField
    fullWidth
    size="small"
    variant="outlined"
    label="Email"
    id="email"
    name="email"
    type="email"
    inputProps={{style: {textTransform: 'lowercase'}}}                
    onChange={props.formik.handleChange}
    onBlur={props.formik.handleBlur}
    value={props.formik.values.email}
    error={props.formik.touched.email && Boolean(props.formik.errors.email)}
    helperText={props.formik.touched.email && props.formik.errors.email}
    InputLabelProps={{
        shrink: true,
    }}

/>                   

Conclusion

In conclusion, validating email addresses is an essential part of any web application that requires user input. Using React and Material UI, you can create a text field to enter email addresses and quickly validate the format or data entered. Throughout this blog post, we walked you through the process of using React and Material UI to validate email addresses and provided a couple of ways to do it. Whether you are an experienced developer or just starting, this tutorial provides a great introduction to using React and Material UI for email validation. It will help you create more user-friendly and error-free web applications for your next project.