Reputation: 13
I'm trying to implement form validation using formik & yup in React. I have a login/register form with three fields (name,email,password). Name field is conditionally rendered when 'create an account' button is clicked. I want the name field to be required only when form is in register state. I'm using a state variable isLogin to save the form's current state, also using it to initialise showName boolean in formik's initialValues. Right now, name field has no validation applied on it and form can be submitted if name field is empty.
My Code
const [isLogin, setIsLogin] = useState(true);
const initialAuthFormValues = {
hideName: isLogin,
name: "",
email: "",
password: "",
};
My Validation Schema
const authFormValidationSchema = Yup.object().shape({
hideName: Yup.boolean(),
name: Yup.string().when("hideName",{
is: false,
then: Yup.string().required("Name is required"),
}),
email: Yup.string().required("Email is required"),
password: Yup.string().required("Password is required"),
});
My Component looks like this
<Formik
initialValues={initialAuthFormValues}
validationSchema={authFormValidationSchema}
onSubmit={submitHandler}
>
{(formik) => (
<Form>
{!isLogin && (
<TextField
label="Name"
type="text"
name="name"
placeholder="Name"
/>
)}
<TextField
label="Email"
type="text"
name="email"
placeholder="Email"
/>
<TextField
label="Password"
type="password"
name="password"
placeholder="Password"
/>
<div className={classes.actions}>
<Button type="submit"> {isLogin ? "Login" : "Create Account"} </Button>
<Button
type="reset"
className="toggle"
onClick={() => { setIsLogin((prevState) => !prevState); }}
>
{isLogin ? "Create new account" : "Login with existing account"}
</Button>
</div>
</Form>
</section>
)}
</Formik>
Upvotes: 1
Views: 1904
Reputation: 126
Finally found the solution to the problem : In my code, action is my prop
let passwordTest
if (action === "Register") {
passwordTest = {
password2: Yup
.string().trim()
.required("Please confirm your password")
.oneOf([Yup.ref('password'), null], 'Passwords must match')
} else {
passwordTest = null
}
Basically above you are saying that if the props is Register (if this form is rendered for registering purpose and not login), then create the field apply the validation listed, otherwise, this field will be null.
const validationSchemaYup = Yup.object().shape({
other fields validation logic...
...passwordTest,
other fields validation logic...
Here you add your new custom validation logic, don't forget to destructure!
Upvotes: 0
Reputation: 1602
You can use authFormValidationSchema as a state , and update this state in case that button clicked :
const authFormValidationSchema = {
email: Yup.string().required("Email is required"),
password: Yup.string().required("Password is required"),
};
const [authFormValidationSchema, setAuthFormValidationSchema] = useState(Yup.object());
track the status when button is clicked in a useEffect, and update state of authFormValues accordingly :
useEffect(()=>{
let authFormValidationSchema_ = JSON.parse(JSON.stringify(authFormValidationSchema))
if(!buttonIsClicked)
setAuthFormValidationSchema(Yup.object(authFormValidationSchema_));
else setAuthFormValidationSchema(Yup.object({...authFormValidationSchema_, name: Yup.string().required("Name is required") }));
},[buttonIsClicked]);
Upvotes: 0