Home > Back-end >  Conditionally rendering 2 Formik components doesn't change initial values
Conditionally rendering 2 Formik components doesn't change initial values

Time:11-05

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>
  );
}

  • Related