Question: How to reset form after submit?
Once the form is submitted, form is not clearing.
Form should clear after submit.
I'm using enableReinitialize={true} to clear the form and it's not working. However handleReset is working but I want this function when I submit the form.
You can call resetForm from your handleSubmit / onSubmit function
@jaredpalmer Is it possible to call resetForm not onSubmit function? I tried to clear the persistent value but unable to do it.. I have been googling but couldn't find any example :( If possible, could you share an example?
@ivanasetiawan I was able to get it to work by supplying the value prop to my input components. I had to pass an empty object into the resetForm function as well or values within Formik would be null.
const onSubmit = async (values, {setSubmitting, setErrors, setStatus, resetForm}) => {
try {
await auth.passwordUpdate(values.oldPassword, values.passwordOne)
resetForm({})
setStatus({success: true})
} catch (error) {
setStatus({success: false})
setSubmitting(false)
setErrors({submit: error.message})
}
}
const PasswordChangeForm = () =>
<Formik
validationSchema={validationSchema}
onSubmit={onSubmit}>
{({errors, handleSubmit, handleChange, isSubmitting, isValid, status, values}) =>
<Form
loading={isSubmitting}
success={!!status && !!status.success}
error={!!errors.submit}
onSubmit={handleSubmit}>
<FormInput
value={values.oldPassword || ''}
onChange={handleChange}
type='password'
placeholder='Old Password'
name='oldPassword'
/>
<FormInput
value={values.passwordOne || ''}
onChange={handleChange}
type='password'
placeholder='New Password'
name='passwordOne'
/>
<FormInput
value={values.passwordTwo || ''}
onChange={handleChange}
type='password'
placeholder='Confirm New Password'
name='passwordTwo'
/>
<Button disabled={!isValid} type='submit'>
Reset My Password
</Button>
</Form>
}
</Formik>
Hi there ... this last suggestion hasn't helped me. Any other ideas as to how to refresh the form after submission. I'm using the render prop method for Formik. I need the input field to clear but the resetForm() method is not having any effect.
// Render Prop
import React from 'react';
import { Formik } from 'formik';
import { addItem} from '../actions/pred-actions.js';
import Button from '@material-ui/core/Button';
import MatInput from '@material-ui/core/Input';
import '../css/addForm.css';
const FormikBasic = ( props ) => {
let { user } = props;
console.log("FormikBasic user:", user);
return (
<div>
<h1>New Item</h1>
<p>Proposed by {user.firstname}</p>
<Formik
initialValues={{
short: ''
}}
validate={values => {
let errors = {};
if (!values.short) {
errors.short = 'Required'
}
return errors;
}}
onSubmit={(
values,
{ setSubmitting, setErrors, resetForm /* setValues and other goodies */ }
) => {
console.log("Form submitted...");
addItem(user, values.short).then(result => {
console.log("addItem result:", result);
setSubmitting(false);
console.log("Add Values:", values);
resetForm({}); // <= This isn't having the effect of clearing the form so the input field is not clearing
// handleReset();
}, errors => {});
render={({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
// resetForm,
handleReset,
isSubmitting,
}) => (
<form onSubmit={handleSubmit}>
<div>
<MatInput
type="textarea"
name="short"
onChange={handleChange}
onBlur={handleBlur}
placeholder="Short name..."
/>
{touched.short && errors.short && <div>{errors.short}</div>}
<Button variant="contained" color="primary" type="submit" disabled={isSubmitting}>
Submit
</Button>
</div>
</form>
)}
/>
</div>
)};
export default FormikBasic;
@notgoodwithpowertools have you tried passing value = values.short || '' to your input component
You sir are a legend. Props to you !! and so fast on the reply too!! Thank you ... been working this all night. This has it working now with the text entry clearing after submit. How do I buy you a beer :-)
<MatInput
value={values.short || ''} // <= Suggested change
type="textarea"
name="short"
onChange={handleChange}
onBlur={handleBlur}
placeholder="Short name..."
/>
Your thanks is more than enough 馃榿
What a headache I got from this. So, yeah, @joserocha3 solution works. In my case, though, I passed the initial values to the resetForm:
const initialValues = { address: '' };
...
<Formik initialValues={initialValues}>
{({ resetForm }) => (
<Form>
<Field name="address" label="Address"/>
<Button
type="button"
onClick={() => resetForm(initialValues)}
>
cancel
</Button>
</Form>
)}
</Formik>
Thanks!
Is there a way to accomplish this when I am using sagas?
Should I send handleReset to a saga and fire it there on successful response?
@flppv Had the same problem here (and with the setSubmitting function), but I didn't wanted to send callbacks to sagas.
My solution : refresh the form state.
How does it look :
export function LoginForm({error, submittedValues}) {
return (
<Formik
key={error ? 'error' : 'form'}
initialValues={submittedValues || initialValues}
render={...}
/>
);
}
// ... connect to redux store ...
submittedValues is populated w/ the form submitted values at the "submitting" stage ;
error is populated w/ the saga error at the "submitted" stage ;
Using key in this way rebuild the whole form (w/ the user inputed values in my case) only once the "submission" flow is ended.
I noticed resetForm() only works if we pass a new value like resetForm({field: "", field2: ""})
so I didn't want to add all my fields manually so what we did is to reset all fields commit from values and then pass thought resetForm(values)
javascript
const onHandleSubmit = () => (
values,
{ setSubmitting, setStatus, resetForm, error }
) => {
addNewClient({ variables: values})
.then(result => {
Object.keys(values).forEach(key => (values[key] = "")); //<-----------RESETTING ALL FIELDS using blank space
resetForm(values); //<--------------PASING TO resetForm the all empty fields
showSuccess(`${result.data.addClient.name} created`);
setStatus(true);
})
.catch(err => {
showGraphQLError(err);
setStatus({ success: false });
setSubmitting(false);
setErrors({ submit: error.message });
});
}
formik.resetForm({}) doesn't clear the form but formik.resetForm() does.
if you are using sagas use a ref to formik and than call
componentDidUpdate(prevProps, prevState) {
// reset form
// some condition ...
this.formik.resetForm();
}
<Formik
ref={(ref) => this.formik = ref}
...
from your component did update method
Hi, not sure if this helps but here is how I handled it using:
export const LogInForm: React.FC<RouterProps> = (props): ReactElement => {
const [userSubmittedFormValues, setUserSubmittedFormValues] = useState({ email: '', password: '' });
return (
<Formik
onReset={(values): void => setUserSubmittedFormValues(values)}
onSubmit={ /* my onSubmit logic here */ }
/* Remainder of my form logic here... */
render={({ values, handleBlur, handleChange, handleRest }): ReactElement => (
<Button onSubmit={handleReset}>Log in</Button>
/>
handleSubmitonReset prop with <Formik />, I set the user submitted values to state in case I need them. Which for my case, I'm using the user submitted values for some error handling I want to do.This way, I'm able to:
Hope this helps.
@rwschmitz
Reset the form on submit immediately
I'd say this is a bad idea. What if the form doesn't submit, or the server responds with an error. you'll make the user refill the form again in order to try to submit one more time.
Can we reset form from outside funtion?
When I reset, the formik.values clears but the form itself keeps the input data. Any ideas?
https://codesandbox.io/s/formik-example-nfl55?fontsize=14&hidenavigation=1&theme=dark
For anyone, here is the solution:
```
validationSchema={validationSchema}
validateOnBlur={false}
validateOnChange={false}
onSubmit={async (values, { resetForm }) => {
await onSubmit(values)
resetForm()
}}
>
@defusioner worked perfectly for me! thanks man
You can reset the form on submission by passing in a second argument in form of an object for your handleSubmit function.
const handleSubmit = async (values, { resetForm }) => {
try {
let res = await axios.post('http://localhost:5003/api/v1/change', values, { headers: { Accept: 'application/json' } });
// console.log(res)
resetForm();
}
catch (err) {
console.log(err);
setErr(err.message);
}
}
<Formik
onSubmit={handleSubmit}
>
...Your form here
</Formik>
Is there a way to accomplish this when I am using sagas?
Should I send handleReset to a saga and fire it there on successful response?
For @flppv anyone else struggling with clearing on submit (but not on error) using sagas, here's how I managed to get it working:
<Formik initialValues={{ ...data }} onSubmit enableReinitialize={!hasError} >
The {...data} comes from the store and is only updated when the submit is successful. onSubmit is a simple dispatch of the values with a saga hooked up to an api.
If submit is not successful, an error is set in the store that ends up as hasError in the above. So the form is only re-initialized with the updated data if there is no error, but if there is an Error then the form can be re-submitted or whatever.
Hi,
I want to reset a specific Field to one particular value. I have a dropdown field, and when I reset, I want to give it a specific value: "Choose Category" in this case.
Does anyone have an idea how to solve this?
<Field name='categoryId' component={CategoryDropDown} />
here is the component:
```import React, { useState, useEffect } from 'react';
import {
UncontrolledDropdown,
DropdownToggle,
DropdownMenu,
DropdownItem
} from 'reactstrap';
import { getCategories } from '../../../client';
const CategoryDropDown = props => {
const [selectedCategoryName, setSelectedCategoryName] = useState('Choose Category');
const [categories, setCategories] = useState([]);
useEffect(() => {
getCategories().then(res => {
setCategories(res.data);
});
}, []);
const handelChange = e => {
setSelectedCategoryName(e.target.name);
props.form.setFieldValue(props.field.name, e.target.value);
};
return (
{selectedCategoryName}
{categories.map(category => (
onClick={handelChange}
value={category.id}
name={category.name}
>
{category.name}
))}
);
};
export default CategoryDropDown;
```
Thank you all guys!
What if we use multiple steps of 3 forms, so after a successful process, we have to return to the first form but this time to begin a new subscription,
resetForm({}) is working but what if we have to alter some fields
import React, { Component } from 'react';
import { Formik } from 'formik';
import * as Yup from 'yup';
const schema = Yup.object({
name: Yup.string().min(3).max(30).required().label('name'),
email: Yup.string().email().required().label('email'),
message: Yup.string().min(10).max(512).required().label('message')
});
class ContactForm extends Component {
onSubmit = async (values, actions) => {
try {
actions.setSubmitting(true);
const resp = await // your API Call .... ;
if (resp.success) {
actions.resetForm();
} else {
// your failure scenario...
}
} catch (err) {
// your error scenario....
}
}
render() {
<Formik initialValues={{name: ''}} validationSchema={schema} onSubmit={this.onSubmit}>
{({ handleSubmit, handleChange, handleBlur, values, errors, touched}) => (
<form onSubmit={handleSubmit}>
<input
value={values.name || ''}
name="name"
type="text"
values={values.name}
onChange={handleChange}
onBlur={handleBlur}
/>
{errors.name && touched.name ? {errors.name} : null }
<button type="submit"> Submit
{isSubmitting ? <Spinner color="#fff" size={24} /> : null}
</button>
</form>
)}
</Formik>
}
}
Thank you,
I solved by splitting the forms into three steps ...
instead of passing anything into the resetForm({}) function use just resetForm(). this worked for me
short: ''
}}
validate={values => {
let errors = {};
if (!values.short) {
errors.short = 'Required'
}
return errors;
}}
onSubmit={(
{ short },
{ setSubmitting, setErrors, resetForm /* setValues and other goodies */ }
) => {
console.log("Form submitted...");
addItem(user, short).then(result => {
console.log("addItem result:", result);
setSubmitting(false);
console.log("Add Values:", values);
resetForm(); // <= Change this
}, errors => {});
i was trying to set form with updated values and after going though comments and test i found following
setValues(updatedValuesObject)Any ideas how to get this working using react native? - Trying the suggestions above but it's still not functioning correctly. :(
Warning: An unhandled error was caught from submitForm() [TypeError: undefined is not an object (evaluating '_ref2.resetForm')]
What a headache I got from this. So, yeah, @joserocha3 solution works. In my case, though, I passed the initial values to the
resetForm:const initialValues = { address: '' }; ... <Formik initialValues={initialValues}> {({ resetForm }) => ( <Form> <Field name="address" label="Address"/> <Button type="button" onClick={() => resetForm(initialValues)} > cancel </Button> </Form> )} </Formik>Thanks!
It's not clearing file input field.
I have Formik form with three field title, description and image. Field "image" type is file. After submitting when I reset form using resetForm(), it's clearing the title and description but image is not clearing. I have also tried resetForm({ title: "", description: "", image: null // and image: "" }) but none of worked.
Have anyone idea how to clear file input also ?
@kishanbharda I had the same issue and I managed it creating a ref in the parent component (the one that use Formik) and passing it to the field using innerRef prop.
Then on the onReset I used the ref to clear the real input value.
const UserForm = props => {
const logoRef = useRef();
const handleReset = (values, formikBag) => {
logoRef.current.value = null; //THIS RESETS THE FILE FIELD
}
const handleSubmit = (values, formikBag) => {
//...
axios({method, url, data})
.then(response => {
formikBag.resetForm();
})
//...
return (
<Formik initialValues={initialValues} onSubmit={handleSubmit} onReset={handleReset}>
...
<Field
type="file"
name="logo"
onChange={({target}) => setFieldValue(props.name, target.files[0])}
innerRef={logoRef}
/>
</Formik>
)
}
Most helpful comment
@ivanasetiawan I was able to get it to work by supplying the
valueprop to my input components. I had to pass an empty object into theresetFormfunction as well orvalueswithinFormikwould be null.