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
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.
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’sseterrors
function doesn’t detect any changes, so it doesn’t trigger a re-render.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.