有条件地渲染 2 个 Formik 组件不会改变初始值

Conditionally rendering 2 Formik components doesn't change initial values

我有条件地渲染 2 个 <Formik/> 组件,但值没有改变

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="jane@acme.com"
                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

在上面的codeandbox中尝试切换并提交

切换后初始值保持不变

内部发生了什么导致这种行为?

React / Formik 必须在两个实例中引用相同的上下文,因为它们在相同的位置呈现。要解决此问题,请在两个表单上放置不同的 'key' 属性。

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="jane@acme.com"
                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>
  );
}