I am conditionally rendering 2 <Formik/>
components but the values do not change
function App() {
const [state, setState] = useState(true);
return (
<div>
<button
onClick={() => {
setState((s) => !s);
}}
>
toggle
</button>
<h1>Sign Up</h1>
{state ? (
<Formik
initialValues={{
firstName: "",
lastName: "",
email: ""
}}
onSubmit={async (values) => {
await new Promise((r) => setTimeout(r, 500));
alert(JSON.stringify(values, null, 2));
}}
>
<Form>
<div>
<label htmlFor="firstName">First Name</label>
<Field id="firstName" name="firstName" placeholder="Jane" />
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<Field id="lastName" name="lastName" placeholder="Doe" />
</div>
<div>
<label htmlFor="email">Email</label>
<Field
id="email"
name="email"
placeholder="[email protected]"
type="email"
/>
</div>
<button type="submit">Submit</button>
</Form>
</Formik>
) : (
<Formik
initialValues={{
fn: "",
ln: ""
}}
onSubmit={async (values) => {
await new Promise((r) => setTimeout(r, 500));
alert(JSON.stringify(values, null, 2));
}}
>
<Form>
<div>
<label htmlFor="fn">F N</label>
<Field id="fn" name="fn" placeholder="Jane" />
</div>
<div>
<label htmlFor="ln">L N</label>
<Field id="ln" name="ln" placeholder="Doe" />
</div>
<button type="submit">Submit</button>
</Form>
</Formik>
)}
</div>
);
}
https://codesandbox.io/s/nifty-fast-4ef5r?file=/src/App.js
In the above codesandbox try to toggle and submit
The initial values remain the same even after toggle
What is happening internally to cause this behaviour?
CodePudding user response:
React / Formik must be referencing the same context in both instances because they are rendered in the same location. To fix this put a different 'key' attribute on the two forms.
function App() {
const [state, setState] = useState(true);
return (
<div>
<button
onClick={() => {
setState((s) => !s);
}}
>
toggle
</button>
<h1>Sign Up</h1>
{state ? (
<Formik
key="1"
initialValues={{
firstName: "",
lastName: "",
email: ""
}}
onSubmit={async (values) => {
await new Promise((r) => setTimeout(r, 500));
alert(JSON.stringify(values, null, 2));
}}
>
<Form>
<div>
<label htmlFor="firstName">First Name</label>
<Field id="firstName" name="firstName" placeholder="Jane" />
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<Field id="lastName" name="lastName" placeholder="Doe" />
</div>
<div>
<label htmlFor="email">Email</label>
<Field
id="email"
name="email"
placeholder="[email protected]"
type="email"
/>
</div>
<button type="submit">Submit</button>
</Form>
</Formik>
) : (
<Formik
key="2"
initialValues={{
fn: "",
ln: ""
}}
onSubmit={async (values) => {
await new Promise((r) => setTimeout(r, 500));
alert(JSON.stringify(values, null, 2));
}}
>
<Form>
<div>
<label htmlFor="fn">F N</label>
<Field id="fn" name="fn" placeholder="Jane" />
</div>
<div>
<label htmlFor="ln">L N</label>
<Field id="ln" name="ln" placeholder="Doe" />
</div>
<button type="submit">Submit</button>
</Form>
</Formik>
)}
</div>
);
}