Reputation: 241
I need some help, I am new to react. I created a Functional Component form with Context API and I am trying to prevent it from submitting if the form failed validation and return false. I have check the validation and it is working by uncommenting the html input button and comment out the React Link (<Link></Link>
) button. I try the code with class component and bind the handleChange
and handleSubmit
inside the constructor and it work: however, I do not want to used the class component. I just want to used the function component.
const Employee = () => {
const ctx = useContext(FormActualContext);
const handleChange = (event) => {
ctx.handleChange({
event,
type: 'employee',
});
};
const validate = () => {
const {
firstName,
lastName,
email,
dateOfBirth,
phoneNum,
} = ctx.formData.employee;
const { employee } = ctx.formErrors;
let {
firstNameError,
lastNameError,
emailError,
dateOfBirthError,
phoneNumError,
} = employee;
firstNameError = !firstName ? 'First name can not be blank' : '';
lastNameError = lastName === '' ? 'Last name can not be blank' : '';
dateOfBirthError = !dateOfBirth ? 'Enter a valid date of birth' : '';
if (!validateEmail(email)) {
emailError =
email === '' ? 'Enter a valid email' : `${email} is not valid email`;
} else {
emailError = '';
}
if (!validatePhoneNumber(phoneNum)) {
phoneNumError =
phoneNum === ''
? 'Enter a valid phone'
: `${phoneNum} is not a valid phone number`;
} else {
phoneNumError = '';
}
if (
firstNameError ||
lastNameError ||
emailError ||
dateOfBirthError ||
phoneNumError
) {
ctx.setFormErrors({
employee: {
...employee,
firstNameError,
lastNameError,
emailError,
dateOfBirthError,
phoneNumError,
},
});
return false;
}
return true;
};
const handleSubmit = (event) => {
event.preventDefault();
const isValid = validate();
if (isValid) {
ctx.reSetEmployee();
}
};
const {
employee: {
firstNameError,
lastNameError,
emailError,
dateOfBirthError,
phoneNumError,
},
} = ctx.formErrors;
return (
<div className="container_fluid">
<div className="registration_form_container">
<div className="register_context">
<form action="" onSubmit={handleSubmit} className="registration_form">
<div className="form-group">
<input
type="text"
name="firstName"
id="firstName"
placeholder={'Enter first name'}
onChange={handleChange}
/>
<span>{firstNameError}</span>
</div>
<div className="form-group">
<input
type="text"
name="lastName"
id="lastName"
placeholder={'Enter last name'}
onChange={handleChange}
/>
<span>{lastNameError}</span>
</div>
<div className="form-group">
<input
type="text"
name="email"
id="email"
placeholder={'Enter email address'}
onChange={handleChange}
/>
<span>{emailError}</span>
</div>
<div className="form-group">
<input
type="date"
name="dateOfBirth"
id="dateOfBirth"
placeholder={'Enter date of birth'}
onChange={handleChange}
/>
<span>{dateOfBirthError}</span>
</div>
<div className="form-group">
<input
type="text"
name="phoneNum"
id="phoneNum"
placeholder={'Enter phone number (international: +1)'}
onChange={handleChange}
/>
<span>{phoneNumError}</span>
</div>
<div className="form-group custom_btn_container">
{/*<input type="submit" className="btn" value="Register"/>*/}
<Link to="/addressForm">
<input type="submit" className="btn" value="Register" />
</Link>
</div>
</form>
</div>
</div>
</div>
);
};
Upvotes: 1
Views: 1006
Reputation: 202696
The issue isn't that the form is being submitted upon validation (true or false), but rather that both field validation and route navigation are more or less occurring at the same time. The Link
, upon being clicked, will immediately navigate to the specified path.
Seems you want to validate the input, and only upon successful validation, call the reSetEmployee
function on the context and navigate to "/addressForm".
I suggest rendering the submit button not within a Link
and use imperative navigation. For this I'm assuming you are using react-router-dom
library.
import { useHistory } from 'react-router-dom';
...
const history = useHistory();
...
const handleSubmit = (event) => {
event.preventDefault();
const isValid = validate();
if (isValid) {
ctx.reSetEmployee();
history.push("/addressForm");
}
};
...
<div className="form-group custom_btn_container">
<input type="submit" className="btn" value="Register"/>
</div>
Upvotes: 1