I'm trying to make a simple form that has validation and after the validation is success send a mail with Email.js. I'm using only email.js. I'm trying to set an if statement that would check that my formErrors object is empty and if it is to "fire" the mail sending. But so far I've tried a few methods but they all send mail even if the form hasn't passed the validation (formErrors object has value). My code here (I removed my service, template and key from .sendForm) with the latest check I attempted (Object.keys(formErrors).length === 0) that still doesn't prevent the mail to be sent:
import React, { useState, useRef } from "react";
import emailjs from "@emailjs/browser";
import "./App.css";
function App() {
const initialValues = { user: "", email: "", pass: "" };
const [formValues, setFormValues] = useState(initialValues);
const [formErrors, setFormErrors] = useState({});
const [isSubmit, setIsSubmit] = useState(false);
const handleChange = (e) => {
const { name, value } = e.target;
setFormValues({ ...formValues, [name]: value });
};
const form = useRef();
const handleSubmit = (e) => {
e.preventDefault();
setFormErrors(validate(formValues));
setIsSubmit(true);
if (Object.keys(formErrors).length === 0) {
emailjs
.sendForm(
"",
"",
form.current,
""
)
.then(
(result) => {
console.log(result.text);
},
(error) => {
console.log(error.text);
}
);
}
};
const validate = (v) => {
const errors = {};
const regex = /^[^\s@] @[^\s@] \.[^\s@]{2,}$/i;
if (!v.user) {
errors.user = "This field can't be empty";
}
if (!v.email) {
errors.email = "This field can't be empty";
} else if (!regex.test(v.email)) {
errors.email = "Incorrect email";
}
if (!v.pass) {
errors.pass = "This field can't be empty";
} else if (v.pass.length < 6) {
errors.pass = "Password needs to be at least 6 characters";
}
return errors;
};
return (
<div className="container">
{Object.keys(formErrors).length === 0 && isSubmit ? (
<div className="title">Success</div>
) : (
<div className="title">Fill the form</div>
)}
<form ref={form} onSubmit={handleSubmit}>
<h1>Login Form</h1>
<hr />
<div className="form">
<div className="field">
<label>Username</label>
<input
type="text"
name="user"
placeholder="Username"
value={formValues.user}
onChange={handleChange}
/>
</div>
<p>{formErrors.user}</p>
<div className="field">
<label>Email</label>
<input
type="text"
name="email"
placeholder="Email"
value={formValues.email}
onChange={handleChange}
/>
</div>
<p>{formErrors.email}</p>
<div className="field">
<label>Password</label>
<input
type="password"
name="pass"
placeholder="Password"
value={formValues.pass}
onChange={handleChange}
/>
</div>
<p>{formErrors.pass}</p>
<button className="btn">Submit</button>
</div>
</form>
</div>
);
}
export default App;
CodePudding user response:
I guess your issue related with non async behaviour of states. In handleSubmit
function you set formErrors
and right after you are checking it in conditional statement. If you replace your
if (Object.keys(formErrors).length === 0)
with
if (Object.keys(validate(formValues)).length === 0)
it should work as expected.
Another solution would be adding this in the beginning of handleSubmit
function and it will not enter to any other logic of the submit
if (Object.keys(validate(formValues)).length > 0) {
return
}