DEV Community

Cover image for The Forbidden Forms: React JS Form Validation Tricks
Josef Held
Josef Held

Posted on • Updated on

The Forbidden Forms: React JS Form Validation Tricks

The Dark Art of Form Validation

Forms are the gatekeepers of the user data in most applications, serving as critical pathways to interactive and dynamic user experiences. However, poorly validated forms can open the floodgates to a chaotic mess of bugs, user frustration, and even security issues. Mastering form validation in React JS not only enhances the integrity of the data collected but also improves the overall user experience, keeping the demons of bad data at bay.

Setting the Stage: Why Validate Forms?

Before we delve into the how, let's establish the why. Validation ensures that the input received meets the standards necessary for processing or storing. This is crucial for a few reasons:

  • Security: Proper validation can prevent malicious data that could exploit vulnerabilities in your system.
  • Data Integrity: Ensures the data is in the right format and meets the criteria necessary for backend processes.
  • User Experience: Helps users correct their errors and provides immediate feedback, which is essential for a smooth interaction.

React Basics: Controlled Components

In React, forms are typically handled by controlled components. This means that form data is handled by the state within the component. Here’s a simple example:

import React, { useState } from 'react';

function SimpleForm() {
  const [input, setInput] = useState('');

  const handleChange = event => {
    setInput(event.target.value);
  };

  const handleSubmit = event => {
    event.preventDefault();
    alert('A name was submitted: ' + input);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input type="text" value={input} onChange={handleChange} />
      </label>
      <button type="submit">Submit</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Implementing Basic Validation

The first line of defense in form validation is implementing basic checks:

  • Required Fields: Ensure that essential fields are not left empty.
  • Pattern Matching: Use regular expressions to enforce the format, such as email addresses or phone numbers.

Here’s how you can extend the simple form to include these validations:

function ValidatedForm() {
  const [email, setEmail] = useState('');
  const [error, setError] = useState('');

  const validateEmail = email => {
    const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return re.test(String(email).toLowerCase());
  };

  const handleChange = event => {
    setEmail(event.target.value);
    if (!validateEmail(event.target.value)) {
      setError('Invalid email format');
    } else {
      setError('');
    }
  };

  const handleSubmit = event => {
    event.preventDefault();
    if (!email) {
      setError('Email is required');
      return;
    }
    if (error) {
      alert('Fix errors before submitting');
      return;
    }
    alert('Email submitted: ' + email);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Email:
        <input type="email" value={email} onChange={handleChange} />
      </label>
      {error && <p style={{color: 'red'}}>{error}</p>}
      <button type="submit">Submit</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Advanced Techniques: Using Libraries

While basic validation is straightforward, complex forms with lots of inputs or dynamic requirements can benefit from specialized libraries. Here are a few popular ones:

  • Formik: Simplifies the form handling and validation process in React. It abstracts the form state management and integrates seamlessly with validation schemas.
  • Yup: Often used with Formik, it allows you to build a validation schema which Formik can utilize to validate the form fields automatically.

Here's how you might set up a form with Formik and Yup:

import React from 'react';
import { useFormik } from 'formik';
import * as Yup from 'yup';

const validationSchema = Yup.object({
  email: Yup.string().email('Invalid email address').required('Required'),
});

function FormikForm() {
  const formik = useFormik({
    initialValues: {
      email: '',
    },
    validationSchema: validationSchema,
    onSubmit: values => {
      alert(JSON.stringify(values, null, 2));
    },
  });

  return (
    <form onSubmit={formik.handleSubmit}>
      <label htmlFor="email">Email</label>
      <input
        id="email"
        type="email"
        {...formik.getFieldProps('email')}
      />
      {formik.touched.email && formik.errors.email ? (
        <div style={{color: 'red'}}>{formik.errors.email

}</div>
      ) : null}
      <button type="submit">Submit</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

React Hooks and Custom Validation

Consider using hooks to create custom validation logic for more control and leverage React’s full potential. Here’s a way to structure custom hooks for form validation:

import React, { useState, useEffect } from 'react';

function useInput(initialValue, validateFunction) {
  const [value, setValue] = useState(initialValue);
  const [isTouched, setIsTouched] = useState(false);

  const isValid = validateFunction(value);
  const hasError = isTouched && !isValid;

  const handleInputChange = event => {
    setValue(event.target.value);
  };

  const handleInputBlur = () => {
    setIsTouched(true);
  };

  return {
    value,
    hasError,
    isValid,
    onChange: handleInputChange,
    onBlur: handleInputBlur
  };
}

// Usage
function CustomHookForm() {
  const validateEmail = email => {
    const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return re.test(String(email).toLowerCase());
  };

  const emailInput = useInput('', validateEmail);

  const handleSubmit = event => {
    event.preventDefault();
    if (!emailInput.isValid) {
      alert('Please enter a valid email');
      return;
    }
    alert('Email submitted: ' + emailInput.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Email:
        <input type="email" {...emailInput} />
      </label>
      {emailInput.hasError && (
        <p style={{color: 'red'}}>Please enter a valid email</p>
      )}
      <button type="submit">Submit</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Conclusion: Mastering Form Validation

By mastering form validation in React JS, you not only ensure that your applications are robust and secure but also provide a seamless and intuitive user experience. Whether you choose to implement basic checks, use libraries like Formik and Yup, or create custom hooks for more complex scenarios, your forms will stand strong against the demons of poor data and user frustration.

Have you encountered any notorious form validation challenges? Share your experiences in the comments below. If you found this guide helpful, consider sharing it with your fellow developers, and don't forget to follow us for more forbidden React JS tips and tricks.

Top comments (0)