Is it possible to timeout and hide the error message of forms after some time in Formik? - reactjs

How can I hide the error message of forms after some time in Formik (React form library).
Is there any method in Formik?
It shows Name is Required, Email is required, Message is required. But I want to hide it after sometime.
Here is my code :
import React from 'react';
import { withFormik, Form, Field } from 'formik';
import * as Yup from 'yup';
import './contact.scss';
const Contact = ({ errors, touched }) => {
return (
<section className="c-section c-contact u-padding-v-xlarge">
<h1>Get in touch</h1>
<p>We&apos;ll love to hear from you!</p>
<Form>
<div>
{touched.name && errors.name ? (
<p style={{ color: 'red' }}>{errors.name}</p>
) : null}
<Field
id="Name"
type="text"
name="name"
autoComplete="name"
placeholder="Your Name"
/>
</div>
<div>
{touched.email && errors.email ? (
<p style={{ color: 'red' }}>{errors.email}</p>
) : null}
<Field
id="message"
type="email"
name="email"
autoComplete="email"
placeholder="Your Email"
/>
</div>
<div>
{touched.message && errors.message ? (
<p style={{ color: 'red' }}>{errors.message}</p>
) : null}
<Field
component="textarea"
name="message"
id="message"
placeholder="Your Message"
/>
</div>
<button type="submit" className="button button--success button--block">
Send Message
</button>
</Form>
</section>
);
};
export default withFormik({
mapPropsToValues: () => ({
name: '',
email: '',
message: '',
}),
validationSchema: Yup.object().shape({
name: Yup.string().required('Name is required'),
email: Yup.string()
.email('Email not valid')
.required('Email is required'),
message: Yup.string().required('Message is required'),
}),
handleSubmit: (values, { resetForm }) => {
// Handle http request here
console.log(values);
setTimeout(resetForm(), 2000);
},
})(Contact);
I have tried setTimeout(resetForm(), 2000); passing resetForm but it doesn't work. Any alternative?

When you do setTimeout(resetForm(), 2000) you are not passing the function (you are calling it) to the setTimeout. You should do setTimeout(resetForm, 2000). If you want to reset errors you can use setErrors like in example https://codesandbox.io/s/941jzvx01p

Related

Yup Was Not Working With Formik and also not provide any type of error

Yup Validation Not Working I Also tried Like This import Yup from 'yup' But Still Not Working.., when I create a simple validate Function without YUP it was worked fine. but when I use YUP that time Validation Not Work.
Added Form Component
import React from 'react';
import { useFormik } from 'formik';
import * as Yup from 'yup';
const initialValues = {
name : "",
surname : "",
address : ""
}
const validateSchema = Yup.object({
name: Yup.string().required('This Field is Required'),
surname: Yup.string().required('This Field is Required'),
address: Yup.string().required('This Field is Required')
});
const onSubmit = values =>{
console.log('FormData->',values);
}
function Form() {
const formik = useFormik({
initialValues ,
onSubmit ,
validateSchema
})
return (
<div className="container x col-md-4 col-md-offset-4" >
<form onSubmit={formik.handleSubmit} >
<div className="form-group">
<input autoComplete="off" onBlur={formik.handleBlur} onChange={formik.handleChange}
value={formik.values.name} name="name" className="name form-control-lg" placeholder="Enter A Name" />
<small>
{formik.touched.name && formik.errors.name ? <div className="error"> {formik.errors.name} </div> : null}
</small>
</div>
<div className="form-group">
<input autoComplete="off" onBlur={formik.handleBlur} onChange={formik.handleChange}
value={formik.values.surname} name="surname" className="surname form-control-lg" placeholder="Enter A Surname" />
<small> { formik.touched.surname && formik.errors.surname ? <div className="error"> {formik.errors.surname} </div> : null} </small>
</div>
<div className="form-group">
<input autoComplete="off" onBlur={formik.handleBlur} onChange={formik.handleChange} value={formik.values.address}
name="address" className="address form-control-lg" placeholder="Enter A Address" />
<small> {formik.touched.address && formik.errors.address ? <div className="error"> {formik.errors.address} </div> : null} </small>
</div>
<button className="btn btn-danger" >Submit</button>
</form>
</div>
)
}
export default Form;
The valid option here is validationSchema not validateSchema. Just set the right one:
const validationSchema = Yup.object({
// ...
});
useFormik({
// ...
validationSchema
})
To use formik and yup, first you have you do npm install yup and npm install formik. if your yarn user then do yarn add formik and yarn add yup.
after that follow this code.
import {Formik} from 'formik';
import * as yup from 'yup';
//functional component am using
export const Auth = () => {
const initialFormValue ={
email: '',password: '',};
const SignInSchema = yup.object().shape({
email: yup.string().email('Invalid Email').required('Email is Required'),
password: yup.string().min(5, 'Too Short').required('Password is Required'),
})
<Formik initialValues={initialFormValue} validationSchema={SignInSchema}
onSubmit={values => console.log(values)}>
{({values, errors, touched, handleChange, handleBlur,
handleSubmit,isSubmitting,
isValid}) => (
<>
<input name='email' type='email' handleChange={handleChange} value=
{values.email} onBlur={handleBlur} label='Email' />
{errors.email && touched.email ? (<Error>{errors.email}</Error>): null}
<input name='password' type='password' handleChange={handleChange} value=
{values.password} onBlur={handleBlur} label='Password' />
{errors.password && touched.password ? (<Error>{errors.password}</Error>):
null}
<button onClick={handleSubmit} type="submit">Send</button>
</>
) }
</Formik>
)}
its not necessary for you to define initial value outside you can do inside formik too <Formik initialValues={email: '', password: ''}> </Formik>
i hope this will help you thank you.

React + Formik + Yup async validation

Formik + yup
validation with .test() triggers on change on every field
example:
i have a validation schema:
const schemaValidation = yup.object().shape({
name: yup.string().required(),
email: yup.string().email().required()
.test( // it runs even if previous validation failed!
'checkEmailExists', 'email already taken.',
// it triggers on every onBlur
email => { console.log('email registration runs') return Promise.resolve(true)}
),
other: yup.string().required()
.test(
'checkOthers', 'error',
val => {console.log('other validation runs'); return Promise.resolve(true)}
)
})
render function on my react component looks like:
...
render () {
return(
<Formik
validateOnChange={false}
validateOnBlur={true}
initialValues={{
name: '',
email: '',
other: ''
}}
validationSchema={schemaValidation}
onSubmit={this.handleSubmit}
>
{(props) => (
<Form>
<div className="field">
<Field className="input" type="email" name="email" placeholder="Email" />
<ErrorMessage name="email" />
</div>
<div className="field">
<Field className="input" type="text" name="name" placeholder="Name"/>
<ErrorMessage name="name" />
</div>
<div className="field">
<Field className="input" type="text" name="other" placeholder="Other"/>
<ErrorMessage name="other" />
</div>
<button type="submit">Submit</button>
</Form>
)}
</Formik>
)
so after every single field changed I receive messages from all .test() validators in console:
email registration runs
other validation runs
versions:
react: 16.13.1
formik: 2.1.4
yup: 0.28.4
By default formik validates after change, blur and submit events. Your code disables validation after change events with validateOnChange={false}. In order to only validate on submit events, try setting validateOnBlur to false too.
https://jaredpalmer.com/formik/docs/guides/validation#when-does-validation-run
https://jaredpalmer.com/formik/docs/api/formik#validateonblur-boolean
Hello everyone in 2022,
I understand a lot of formik has changed over the years - but thought I share a relevant solution that's using touched property, feel free to peek at https://codesandbox.io/s/stack-overflow-54204827-llvkzc.
And also shared for another StackOverflow question here, React Native Form Validation.
In summary, it's basically used like below (with yup outside of this snippet), to decide whether to show (if any) input validation errors:
<Formik
initialValues={{
email: "",
password: ""
}}
validationSchema={LoginSchemaA}
onSubmit={(
values: Values,
{ setSubmitting }: FormikHelpers<Values>
) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 500);
}}
>
{({ errors, touched }) => (
<Form>
<label htmlFor="email">Email</label>
<Field
id="email"
name="email"
placeholder="john.doe#email.com"
type="email"
/>
{errors.email && touched.email ? (
<div style={{ color: "red" }}>{errors.email}</div>
) : null}
<label htmlFor="password">Password</label>
<Field id="password" name="password" type="password" />
{errors.password && touched.password ? (
<div style={{ color: "red" }}>{errors.password}</div>
) : null}
<button type="submit">Submit</button>
</Form>
)}
</Formik>
And as package.json reference, below are the defined versions:
"dependencies": {
...
"formik": "2.2.9",
...
"yup": "0.32.11"
},
Hope this helps for those on these mentioned formik and yup versions above!

onchange in a form using formik the value of the field is not updated

I'm new to react, and I'm trying to apply validations to a form.
For some reason when adding the property:
onChange={onChange}
I want to send the values to the parent component. That's why I'm using the onchange.
Nothing I write is shown in my text fields, why does this happen?
export const Son = props => {
const { onChange } = props;
return (
<Formik
initialValues={{
fullname: "",
email: ""
}}
validationSchema={Yup.object().shape({
fullname: Yup.string()
.min(2, "Your name is too short")
.required("Please enter your full name"),
email: Yup.string()
.email("The email is incorrect")
.required("Please enter your email")
})}
onSubmit={(values, { setSubmitting }) => {
const timeOut = setTimeout(() => {
console.log(values);
setSubmitting(false);
clearTimeout(timeOut);
}, 1000);
}}
>
{({
values,
errors,
touched,
handleSubmit,
isSubmitting,
validating,
valid
}) => {
return (
<Form name="contact" method="post" onSubmit={handleSubmit}>
<label htmlFor="fullname">
Fullname
<Field
type="text"
name="fullname"
autoComplete="name"
placeholder="your fullname"
onChange={onChange}
/>
</label>
{<ErrorMessage name="fullname">{msg => <p>{msg}</p>}</ErrorMessage>}
{/*errors.fullname && touched.fullname && <p>{errors.fullname}</p>*/}
<br />
<label htmlFor="email">
Email
<Field
type="email"
name="email"
autoComplete="email"
placeholder="your email"
onChange={onChange}
/>
</label>
<ErrorMessage name="email">{msg => <p>{msg}</p>}</ErrorMessage>
<br />
<button type="submit" disabled={!valid || isSubmitting}>
{isSubmitting ? `Submiting...` : `Submit`}
</button>
</Form>
);
}}
</Formik>
);
};
this is my live code:
https://stackblitz.com/edit/react-qotvwb?file=components/son_component.js
you're not using the formik handleChange at all.
I highlighted the changes that I made in https://stackblitz.com/
and you can test this working here

How to add Radio Button in Formik Validations Reactjs?

I am using Formik for Validating my Registration form I want to add validate gender via radio button how can I do that. I am not able to add radio button.
This is what I have done:-
const SignupSchema = Yup.object().shape({
email: Yup.string()
.email('Invalid email')
.required('Required'),
password: Yup.string()
.min(4, 'Password Must be four characters long!')
.max(20, 'Too Long!')
.required('Required'),
});
class Register extends Component {
render() {
return (
<Formik
initialValues={{
email: '',
password:'',
gender:'',
}}
validationSchema={SignupSchema}
onSubmit={values => {
console.log(values);
}}
>
{({ errors, touched }) => (
<Form>
<Field style={customStyles.textfield} placeholder="Email" name="email" type="email" />
{errors.email && touched.email ? <div}>{errors.email}</div> : null}
<Field placeholder="Enter Password" name="password" type="password" />
{errors.password && touched.password ? <div >{errors.password}</div> : null}
<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
)
}
}
change gender initialValues as male
<Field
name="gender"
render={({ field }) => (
<>
<div className="radio-item">
<input
{...field}
id="male"
value="male"
checked={field.value === 'male'}
name="type"
type="radio"
/>
<label htmlFor="male">Male</label>
</div>
<div className="radio-item">
<input
{...field}
id="female"
value="female"
name="type"
checked={field.value === 'female'}
type="radio"
/>
<label htmlFor="female">Female</label>
</div>
</>
)}
/>
This solution gives you the chance to have more than 2 options.
Let say you have a file called Main.js and you want to put a radio button input in it. First, provide a list of options for your radio button in the Main.js
const radioOptions = [
{ key: 'Option 1', value: 'value 1' },
{ key: 'Option 2', value: 'value 2' },
{ key: 'Option 3', value: 'value 3' }
];
Next, create a RadioButton.js file with below code
import React from 'react';
import { Field } from 'formik';
const RadioButton = (props) => {
const { label, name, options, ...rest } = props;
return (
<div>
<label htmlFor={name}>{label}</label>
<Field name={name} {...rest} >
{
({ field }) => {
return options.map(option => {
return (
<React.Fragment key={option.key}>
<input
type='radio'
id={option.id}
{...field}
value={option.value}
checked={field.value === option.value}
/>
<label htmlFor={option.id}>{option.key}</label>
</React.Fragment>
);
})
}
}
</Field>
</div>
);
};
export default RadioButton;
Then put the reusable RadioButton Component in the Main.js wherever you want the radio button input to render.
The result UI will be 3 radio buttons with values "value 1", "value 2" and "value 3".
You can check out this awesome youtube series to know more.
This can be done simply but using this code below. it worked for me:
You will need to import Formik from "formik"
<Formik
initialValues={{
email: '',
password:'',
gender:'',
}}
// validations
validationSchema={SignupSchema}
onSubmit={values => { console.log(values); }}
>
{(formik) => (
<Form onSubmit={formik.handleSubmit}>
//Your Other inputs........
<div className="custom-control">
<input
id="male"
type="radio"
value="male"
name='gender'
onChange={formik.handleChange}
defaultChecked={formik.values.gender=== "male"}
/>
<label
className="custom-control-label"
htmlFor="male"
>
Male
</label>
</div>
<div className="custom-control">
<input
id="female"
type="radio"
value="female"
name='gender'
onChange={formik.handleChange}
defaultChecked={formik.values.gender=== "female"}
/>
<label
className="custom-control-label"
htmlFor="female"
>
Female
</label>
</div>
//Your Other inputs......
<button type="submit">Submit</button>
</Form>
)}
</Formik>

Submitting Formik form data to firebase database in react

I am trying to figure out how to send form data form a Formik form to a Firebase database in my react app.
I have a form as follows:
import React from 'react'
import { Link } from 'react-router-dom'
// import { Formik } from 'formik'
import { Formik, Form, Field, ErrorMessage, withFormik } from 'formik';
import * as Yup from 'yup';
import { Badge, Button, Col, Feedback, FormControl, FormGroup, FormLabel, InputGroup } from 'react-bootstrap';
import Select from 'react-select';
import firebase from '../../../firebase';
const style1 = {
width: '60%',
margin: 'auto'
}
const style2 = {
paddingTop: '2em',
}
const style3 = {
marginRight: '2em'
}
const style4 = {
display: 'inline-block'
}
const options = [
{ value: 'author', label: 'Author' },
{ value: 'reviewer', label: 'Reviewer' },
];
class Basic extends React.Component {
state = {
selectedOption: null,
}
handleChange = (selectedOption) => {
this.setState({ selectedOption });
console.log(`Option selected:`, selectedOption);
}
render() {
const { selectedOption } = this.state;
return (
<Formik
initialValues={{
firstName: '',
lastName: '',
email: '',
password: '',
confirmPassword: '',
selectedOption: null
}}
validationSchema={Yup.object().shape({
firstName: Yup.string()
.required('First Name is required'),
lastName: Yup.string()
.required('Last Name is required'),
email: Yup.string()
.email('Email is invalid')
.required('Email is required'),
selectedOption: Yup.string()
.required('It will help us get started if we know a little about your background'),
password: Yup.string()
.min(6, 'Password must be at least 6 characters')
.required('Password is required'),
confirmPassword: Yup.string()
.oneOf([Yup.ref('password'), null], 'Passwords must match')
.required('Confirm Password is required')
})}
// onSubmit={fields => {
// alert('SUCCESS!! :-)\n\n' + JSON.stringify(fields, null, 5))
// }}
// onSubmit={handleSubmit}
render={({ errors, status, touched }) => (
<Form style={style1}>
<h1 style={style2}>Get Started</h1>
<div className="form-group">
<label htmlFor="firstName">First Name</label>
<Field name="firstName" type="text" className={'form-control' + (errors.firstName && touched.firstName ? ' is-invalid' : '')} />
<ErrorMessage name="firstName" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" type="text" className={'form-control' + (errors.lastName && touched.lastName ? ' is-invalid' : '')} />
<ErrorMessage name="lastName" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="email">Email</label>
<Field name="email" type="text" placeholder="Please use your work email address" className={'form-control' + (errors.email && touched.email ? ' is-invalid' : '')} />
<ErrorMessage name="email" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<Field name="password" type="password" className={'form-control' + (errors.password && touched.password ? ' is-invalid' : '')} />
<ErrorMessage name="password" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="confirmPassword">Confirm Password</label>
<Field name="confirmPassword" type="password" className={'form-control' + (errors.confirmPassword && touched.confirmPassword ? ' is-invalid' : '')} />
<ErrorMessage name="confirmPassword" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="selectedOption">Which role best describes yours?</label>
<Select
value={selectedOption}
onChange={this.handleChange}
options={options}
/>
</div>
<div className="form-group" >
<label htmlFor="consent">By registering you accept the <Link to={'/Terms'}>Terms of Use</Link> and <Link to={'/Privacy'}>Privacy Policy</Link> </label>
</div>
<div className="form-group">
<Button variant="outline-primary" type="submit" style={style3} id="submitRegistration">Register</Button>
</div>
</Form>
)}
/>
);
}
}
export default Basic;
I have a database in firebase (cloud firestore) with a collection called Registrations that has fields named the same as each of these form fields.
I have spent the day following tutorials that seem to be made for react before Formik. There's not much point to showing all the things I've tried and failed at for the day - they're clearly not written with Formik in mind. I can't find a way to write the onSubmit so that Formik can give the data to Firebase.
Has anyone found a current tutorial or know how to do this?
I've used Formik and Firebase in this Open-Source React project. Maybe this is what you're looking for :)
Expertizo React Native Kit

Resources