无法在表单提交时使用 Formik 执行 React 状态更新

Can't perform a React state update with Formik on form submit

当我单击按钮提交表单时收到以下警告:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
Formik@http://localhost:3000/static/js/vendors~main.chunk.js:3815:28
div
div
CheckIn@http://localhost:3000/static/js/main.chunk.js:382:17
Route@http://localhost:3000/static/js/vendors~main.chunk.js:43553:29

表单有效时出现警告。第二次单击按钮后,它成功提交。

import React from "react";
import { Formik } from "formik";
import { useHistory } from "react-router-dom";

export default function CheckIn({ user, setUser }) {
  const history = useHistory();

  return (
    <div>
        <Formik
          initialValues={{
            name: "",
            mail: ""
          }}
          validate={(values) => {
            const errors = {};

            if (!values.mail && user.mail) {
              values.mail = user.mail;
            }

            if (!values.name && user.name) {
              values.name = user.name;
            }

            if (!values.mail) {
              errors.mail = "Required";
            } else if (
              !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.mail)
            ) {
              errors.mail = "Invalid mail address";
            }

            return errors;
          }}
          onSubmit={(values, { setSubmitting }) => {
            history.push("/success");
            setUser(values);
            setSubmitting(false);
          }}
        >
          {({
            values,
            errors,
            handleChange,
            handleBlur,
            handleSubmit,
            isSubmitting,
          }) => (
            <form onSubmit={handleSubmit}>
              <input
                type="name"
                name="name"
                placeholder="Name"
                style={errors.name ? { border: "2px solid red" } : {}}
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.name || user.name}
              />
              <input
                type="email"
                name="mail"
                placeholder="E-Mail"
                style={errors.mail ? { border: "2px solid red" } : {}}
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.mail || user.mail}
              />

              <button
                type="submit"
                disabled={isSubmitting}
                className="btn wide"
              >
                Checkin
              </button>
            </form>
          )}
        </Formik>
      </div>
  );
}

不幸的是,这个警告对我没有帮助,一方面我不明白,另一方面,也没有 useEffect。

问题:history.push

此错误是由您的表单的 onSubmit 处理程序引起的:

onSubmit={(values, { setSubmitting }) => {
  history.push("/success");
  setUser(values);
  setSubmitting(false);
}}

您要做的第一件事是调用 history.push,它会离开页面并导致 Formik 组件卸载。然后你调用 setSubmitting 尝试更新 Formik 组件的状态 - 但它已经卸载所以你得到错误 "Can't perform a React state update on an unmounted组件。"

只是将 history.push 移动到列表中的最后一个操作导致错误消失,但我不喜欢这个解决方案,因为 React setState 调用是异步的所以在技术上仍然有可能发生错误。我不明白为什么您在离开此页面时需要手动调用 setSubmitting,因此我的建议是完全删除该调用。

onSubmit={(values) => {
  setUser(values);
  history.push("/success");
}}

确保 setUser 没有更新将被导航卸载的组件的状态。