I have recently started learning react and I have a component that has a login form:
import Joi from "joi";
import { useState } from "react";
const Login = () => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const loginSchema = Joi.object().keys({
username: Joi.string().required(),
password: Joi.string().required(),
});
const [errors, setErrors] = useState({ username: null, password: null });
const handleSubmit = (form) => {
form.preventDefault();
validate();
};
const validate = () => {
const { error } = loginSchema.validate(
{ username, password },
{ abortEarly: false }
);
if (!error) return null;
for (const item of error.details) {
let key = item.path[0];
let value = item.message;
setErrors({ ...errors, [key]: value });
}
return errors;
};
return (
<div className="container">
<div>
<h1>Login</h1>
</div>
<div className="card">
<div className="card-body">
<form onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="username">Username</label>
<input
name="username"
type="text"
className="form-control"
id="username"
placeholder="Enter username"
value={username}
onChange={(username) => setUsername(username.target.value)}
/>
{errors.username && (
<div className="alert alert-danger">{errors.username}</div>
)}
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
name="password"
type="password"
className="form-control"
id="password"
placeholder="Password"
value={password}
onChange={(password) => setPassword(password.target.value)}
/>
{errors.password && (
<div className="alert alert-danger">{errors.password}</div>
)}
</div>
<button type="submit" className="btn btn-primary">
Submit
</button>
</form>
{/* Delete later */}
<h4>{JSON.stringify(errors)}</h4>
</div>
</div>
</div>
);
};
export default Login;
Here, I am trying to set the values of username and password in the errors object, but for some reason, only the password property gets set, the username property remains null. I have used object destructuring but it still doesn't set the value, please help.
State updates are not reflected immediately in React, and since you loop over your data to set the errors object multiple times, it only sets in the last key due to batching in event handlers and the fact that state updates are affected by closures.
You should instead create an updated objected and set it in state once