I currently have a form I am building using formik. I am able to update each of the fields(name, email, phone) as expected. The issue I am running into is when I provide one of the formik intial values with a state value and update that state. The act of updating the state causes the form to pletely reset the input fields Is there a way to update the test state without resetting the entire form?? My code is as follows:
import { useState } from "react";
import { Formik, FieldArray } from "formik";
import "./styles.css";
export default function App() {
const [test, setTest] = useState(null);
return (
<Formik
enableReinitialize
initialValues={{
test: test,
name: "",
email: "",
phone: ""
}}
>
{({
values,
touched,
errors,
handleChange,
handleBlur,
handleSubmit
}) => (
<>
<button onClick={() => setTest("something")}>Update State</button>
<br />
<input
placeholder="name"
type="text"
name="name"
value={values.name}
onChange={handleChange}
/>
<br />
<input
placeholder="email"
type="text"
name="email"
value={values.email}
onChange={handleChange}
/>
<br />
<input
placeholder="phone"
type="text"
name="phone"
value={values.phone}
onChange={handleChange}
/>
<>
<pre style={{ textAlign: "left" }}>
<strong>Values</strong>
<br />
{JSON.stringify(values, null, 2)}
</pre>
<pre style={{ textAlign: "left" }}>
<strong>Errors</strong>
<br />
{JSON.stringify(errors, null, 2)}
</pre>
</>
</>
)}
</Formik>
);
}
In order to replicate what I am talking about in the codesandbox first update the name, email, and phone number. Then hit the udate state button and everything will be reset
codesandbox =/src/App.js:0-1567
I currently have a form I am building using formik. I am able to update each of the fields(name, email, phone) as expected. The issue I am running into is when I provide one of the formik intial values with a state value and update that state. The act of updating the state causes the form to pletely reset the input fields Is there a way to update the test state without resetting the entire form?? My code is as follows:
import { useState } from "react";
import { Formik, FieldArray } from "formik";
import "./styles.css";
export default function App() {
const [test, setTest] = useState(null);
return (
<Formik
enableReinitialize
initialValues={{
test: test,
name: "",
email: "",
phone: ""
}}
>
{({
values,
touched,
errors,
handleChange,
handleBlur,
handleSubmit
}) => (
<>
<button onClick={() => setTest("something")}>Update State</button>
<br />
<input
placeholder="name"
type="text"
name="name"
value={values.name}
onChange={handleChange}
/>
<br />
<input
placeholder="email"
type="text"
name="email"
value={values.email}
onChange={handleChange}
/>
<br />
<input
placeholder="phone"
type="text"
name="phone"
value={values.phone}
onChange={handleChange}
/>
<>
<pre style={{ textAlign: "left" }}>
<strong>Values</strong>
<br />
{JSON.stringify(values, null, 2)}
</pre>
<pre style={{ textAlign: "left" }}>
<strong>Errors</strong>
<br />
{JSON.stringify(errors, null, 2)}
</pre>
</>
</>
)}
</Formik>
);
}
In order to replicate what I am talking about in the codesandbox first update the name, email, and phone number. Then hit the udate state button and everything will be reset
codesandbox https://codesandbox.io/s/wispy-sun-mzeuy?file=/src/App.js:0-1567
Share Improve this question asked Feb 25, 2021 at 16:05 Rob TerrellRob Terrell 2,5624 gold badges21 silver badges47 bronze badges2 Answers
Reset to default 10This is because you are initializing the Formik ponent with enableReinitialize
set to true
:
enableReinitialize?: boolean
Default is false. Control whether Formik should reset the form if initialValues changes (using deep equality).
When the state variable test
is updated, the formik-values are reinitialized to the values set in initialValues
.
If you want this to work, I've forked your sandbox and modified it to use the formik hook (without enableReinitialize
) in bination with a useEffect
to manually update the value from state:
const [test, setTest] = useState(null);
const { values, errors, handleChange, setFieldValue } = useFormik({
initialValues: {
test: test,
name: "",
email: "",
phone: ""
}
});
useEffect(() => {
setFieldValue("test", test);
}, [test]);
My solution for this problem was to use the Formik values as state and set it directly with setFieldValue
, so enableInitialize
would not be triggered.
export default function App() {
//const [test, setTest] = useState(null); // This removed
return (
<Formik
enableReinitialize
initialValues={{
test: "",
name: "",
email: "",
phone: ""
}}
>
...
<button onClick={() => setFieldValue("test", "something")}>Update State</button>
Mostly the reason you would want to use states outside of Formik is to use it outside of Formik (ok clear), but this way you still can trigger a function from outside of Formik which you pass the values
and the setFieldValue
- Function to do whatever when triggered e.g. at onChange
of a Formik field:
const handlerDefinedOutside = (values: any, setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void): void => { /* do stuff */ };
<TextField
onChange={(e) => {
handleChange(e);
handlerDefinedOutside(values, setFieldValue);
}}
/>