skip to Main Content

When i am clicking on submit button error not showing in form validation. But when i am changing any text in input field it’s giving errors. Like i am not filling fname field and submitting form it’s not showing anything on UI but when i type a single letter than it’s showing error. please help and let me now what is wrong in below code block?

import React from "react";
import { useState } from "react";
const Login = () => {
  const [value, setValue] = useState({
    fname: "",
    email: "",
    password: "",
    confirmPassword: "",
    gender: "",
    error: {},
  });

  const [errors,seterrors] = useState({
    fname: "",
    email: "",
    password: "",
    confirmPassword: "",
    gender: "",
    error: {},
  });

  const validateForm = () => {
    if (!value.fname) {
      errors.fname = "Name is required";
    }
    if(!value.email){
      errors.email = "Email is required";
    }
    else if(!/^[^s@]+@{1}[a-z]{5,}.{1}[w]{3,}$/.test(value.email)) {
       errors.error = "Email id invalid";
    }
    if(!value.password){
      errors.password="Password is required";
    }
    else if(value.password.length<6){
      errors.password = "Password must be at least of 6 digits long";
    }
    if(!value.confirmPassword){
      errors.confirmPassword="please confirm the password";
    }
    else if(value.password!==value.confirmPassword)
    {
      errors.confirmPassword="Password doesnot match";
    }
    return errors;
   
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    const validationErrors = validateForm();
    console.log(validationErrors);
    console.log(value);
    if(Object.keys(validationErrors).length>0){
      seterrors(validationErrors);
    }
    else{console.log("form submitted");}
    
    
  };
  
  return (
    <div className="maincontainer flex items-center justify-center ">
      <div className="w-6/12 h-max bg-yellow-600 mt-10 flex items-center  justify-center ">
        <form onSubmit={handleSubmit} className=" pt-10 flex flex-col">
          <label
            htmlFor="fname"
            className="text-2xl text-rose-800 font-bold flex justify-between"
          >
            First Name : 
            <input
              type="text"
              id="fname"
              onChange={(e) => setValue({ ...value, fname: e.target.value })}
              placeholder="Type your first name"
              className="p-2 ml-5"
            />
          </label>
          {errors.fname}

          <label
            htmlFor="email"
            className="text-2xl text-rose-800 font-bold  mt-5 flex justify-between"
          >
            Email ID :
            <input
              type="email"
              id="email"
              onChange={(e) => setValue({ ...value, email: e.target.value })}
              placeholder="Type your email id"
              className="p-2 ml-5"
            />
          </label>
          {errors.email}
          <label
            htmlFor="password"
            className="text-2xl text-rose-800 font-bold  mt-5 flex justify-between"
          >
            Password :
            <input
              type="password"
              id="password"
              onChange={(e) => setValue({ ...value, password: e.target.value })}
              placeholder="Type your password"
              className="p-2 ml-5"
            />
          </label>
          <label
            htmlFor="confirmPassword"
            className="text-2xl text-rose-800 font-bold  mt-5 flex justify-between"
          >
            Confirm Password :
            <input
              type="password"
              id="confirmPassword"
              onChange={(e) =>
                setValue({ ...value, confirmPassword: e.target.value })
              }
              placeholder="Type your password"
              className="p-2 ml-5"
            />
          </label>
          <label
            htmlFor="confirm-password"
            className="text-2xl text-rose-800 font-bold  mt-20"
          >
            Gender :
            <select className="p-1 ml-6">
              <option
                onChange={(e) => setValue({ ...value, fname: e.target.value })}
              >
                Male
              </option>
              <option
                onChange={(e) => setValue({ ...value, fname: e.target.value })}
              >
                Female
              </option>
            </select>
          </label>

          <button className="w-40 h-12 bg-indigo-500 mt-10 mb-10" type="submit">
            Submit
          </button>
        </form>
      </div>
    </div>
  );
};

export default Login;

2

Answers


  1. You are directly mutating the error state in function which is not allowed.
    Instead create a new error object and return and also there are many ways to optimize this thing.

    const validateForm = () => {
    // Here create a new variable to store error message or redeclare error to function scope.
    let errors: any = {};
    if (!value.fname) {
      errors.fname = "Name is required";
    }
    if (!value.email) {
      errors.email = "Email is required";
    }
    else if (!/^[^s@]+@{1}[a-z]{5,}.{1}[w]{3,}$/.test(value.email)) {
      errors.error = "Email id invalid";
    }
    if (!value.password) {
      errors.password = "Password is required";
    }
    else if (value.password.length < 6) {
      errors.password = "Password must be at least of 6 digits long";
    }
    if (!value.confirmPassword) {
      errors.confirmPassword = "please confirm the password";
    }
    else if (value.password !== value.confirmPassword) {
      errors.confirmPassword = "Password doesnot match";
    }
    return errors;
    
    
    };
    
    Login or Signup to reply.
  2. Solution 1: (Instant Fix)

    At a minimum, you need to update the handleSubmit function.

    Currently, you’re directly modifying the errors state, which is not a good practice. React relies on immutability to efficiently determine when components need to re-render. When you directly change the state, React’s seterrors function doesn’t detect any changes, so it doesn’t trigger a re-render.

    const handleSubmit = e => {
      e.preventDefault();
      const validationErrors = validateForm();
      if (Object.keys(validationErrors).length > 0) {
        seterrors({ ...validationErrors });
      } else {
        console.log('form submitted');
      }
    };
    

    Solution 2: (Better Approach)

    However, the best practice is to create a clone of the errors object, make your modifications to the clone, and then update the state with the new object. This approach aligns with React’s emphasis on immutability and ensures that the state is correctly updated. By consistently following this pattern, you reduce the risk of introducing subtle bugs and ensure that your component re-renders appropriately whenever the state changes.

    Additionally, by cloning the state and working with the clone, you avoid potential side effects that can arise from mutating the original state object, making your code more predictable and easier to debug.

    const validateForm = () => {
      const updatedErrors = { ...errors };
      if (!value.fname) {
        updatedErrors.fname = 'Name is required';
      }
      if (!value.email) {
        updatedErrors.email = 'Email is required';
      } else if (!/^[^s@]+@{1}[a-z]{5,}.{1}[w]{3,}$/.test(value.email)) {
        updatedErrors.error = 'Email id invalid';
      }
      if (!value.password) {
        updatedErrors.password = 'Password is required';
      } else if (value.password.length < 6) {
        updatedErrors.password = 'Password must be at least of 6 digits long';
      }
      if (!value.confirmPassword) {
        updatedErrors.confirmPassword = 'please confirm the password';
      } else if (value.password !== value.confirmPassword) {
        updatedErrors.confirmPassword = 'Password doesnot match';
      }
      return updatedErrors;
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search