I have a contact form I have created with validation and it mostly works however it still submits even when the information is wrong. Here is my code:
ContactForm.jsx:
const ContactForm = () => {
// react states for required field inputs
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [subject, setSubject] = useState('');
const [message, setMessage] = useState('');
// react state for confirmation of message sent
const [show, setShow] = React.useState(true);
// To set focus on each input field and return error when field is not properly filled
const [ focused, setFocused ] = React.useState({});
const handleBlur = (e) => {
setFocused(prev => ({...prev, [e.target.name]: true}))
}
// For focusing the input field for correct information
const isFocused = (name) => {
return focused[name] === true
}
// the handle submit function combined with EmailJs
const handleSubmit = (e) => {
e.preventDefault();
const serviceId = '';
const templateId = '';
const publicKey = '';
// To create an object that contains template parameter
const templateParams = {
from_name: name,
from_email: email,
from_subject: subject,
to_name: 'Lucy',
message: message,
}
// sends email using emailjs, passing params
emailjs.send(serviceId, templateId, templateParams, publicKey)
.then((response) => {
console.log('Email sent successfully', response);
setName('');
setEmail('');
setSubject('');
setMessage('');
})
.catch((error) => {
console.error('Error sending email:', error)
})
// Displays confirmation once form is submitted
setShow(false);
}
return (
<>
{show ? (
<form onSubmit={handleSubmit} className='form'>
<div className='textbox name'>
<input
name='from_name'
value={name}
type='text'
placeholder='Your Name'
pattern='^[A-Za-z]{2,16}$'
onBlur={handleBlur}
onChange={(e) => setName(e.target.value)}
data-focused={isFocused('from_name').toString()}
required
/>
<span>Please fill in this field</span>
</div>
<div className='textbox email'>
<input
name='from_email'
value={email}
type='email'
placeholder='Your Email'
onBlur={handleBlur}
onChange={(e) => setEmail(e.target.value)}
data-focused={isFocused('from_email').toString()}
required
/>
<span>Please fill in this field</span>
</div>
<div className='textbox subject'>
<select
name='from_subject'
value={subject}
onBlur={handleBlur}
onChange={(e) => setSubject(e.target.value)}
data-focused={isFocused('from_subject').toString()}
required
>
<option value=''>What is your enquiry about?</option>
<option value='General'>General</option>
<option value='Review'>Review</option>
<option value='Business'>Business</option>
<option value='Other'>Other</option>
</select>
<span>Please select an appropiate subject</span>
</div>
<div className='textbox message'>
<textarea
name='message'
value={message}
cols="30"
rows="15"
minLength={100}
placeholder='What is your message to us about? Any specifics, please add here.'
onBlur={handleBlur}
onChange={(e) => setMessage(e.target.value)}
data-focused={isFocused('message').toString()}
required
/>
<span>Message needs to be at least 100 characters long</span>
</div>
<div >
<button
disabled={!name | !email | !subject | !message }
className='message-submit-btn'
onBlur={handleBlur}
type='button'
onClick={(e) => handleSubmit(e)}
>
SUBMIT MESSAGE
</button>
</div>
</form>
) : (
<div className='sent-confirm'>
<CircleCheckBig
style={{color: 'var(--btn-green)'}}
strokeWidth={0.4}
size={400}/>
<p className='sent-confirm-text'>Message Sent!</p>
</div>
)}
</>
);
}
export default ContactForm
ContactUs.css. This css code is used to display the error if occurs:
/* validation code */
.form input:invalid[data-focused='true'] {
border-color: red;
}
.form input:invalid[data-focused='true'] ~ span {
color: red;
display: block;
}
.form select:invalid[data-focused='true'] {
border-color: red;
}
.form select:invalid[data-focused='true'] ~ span {
color: red;
display: block;
}
.form textarea:invalid[data-focused='true'] {
border-color: red;
}
.form textarea:invalid[data-focused='true'] ~ span {
color: red;
display: block;
}
...
/* submit button */
.message-submit-btn {
background: var(--btn-green);
padding: 1rem;
border-radius: 3px;
border: none;
color: white;
letter-spacing: 1.5px;
font-size: 0.88rem;
cursor: pointer;
margin-top: 1em;
}
.message-submit-btn:disabled {
cursor: default;
opacity: 0.5;
transform: scale(1) !important;
}
What is it that I am doing wrong? Any suggestions would very much be appreciated, thank you.
2
Answers
Technically no it doesn’t. What does happen is the
handleSubmit
function is called. But it’s not being called by the form submitting. It’s being called by clicking the button:Validation doesn’t prevent the user from clicking a button.
The form is already calling
handleSubmit
when it’s submitted:There’s no need to call it twice. Just remove that
onClick
handler from the button. (And removetype="button"
so the button will submit the form.)In React, if you want the form to handle validation and submission properly, you need to set the button’s type to ‘submit’ so that the form’s native validation rules are enforced. Also, the onClick handler should be removed because the onSubmit event is already bound to the form.
Fix: