如何使用 Prompt 停止在 formik 脏状态下的导航

How can Prompt be used to stop navigation on formik dirty state

我在 reactjs 项目中使用 formik,我想使用 react-router 中的 Prompt 在用户离开并丢失对其提交的更改之前打开通知.

我期望这样的东西能起作用:

<Prompt
    when={formik.dirty}
    message="You have unsaved changes. Are you sure you want to leave?"
/>

我的 formik 块看起来像这样:

const formik = useFormik({
    initialValues: {
        <values>
    },
    enableReinitialize: true,
    validate,
    onSubmit: values => {
        <submit functional stuff>
    }
}); 

我的表格是这样的:

<form id="myForm" onSubmit={formik.handleSubmit}>
    <div className="row">
        <div className="form-group">
            <label htmlFor="name">Name</label>
            <input
                id="name"
                type="text"
                onChange={formik.handleChange}
                value={formik.values.name}
                className="form-control"
                placeholder="Enter name"
                disabled={isDisabled}
            />
            {formik.errors.name ? <div className="text-danger">{formik.errors.name}</div> : null}
        </div>
        <div className="form-group">
            <label htmlFor="subject">Subject</label>
            <input
                id="subject"
                type="text"
                onChange={formik.handleChange}
                value={formik.values.subject}
                className="form-control"
                placeholder="Email subject"
                disabled={isDisabled}
            />
            {formik.errors.subject ? <div className="text-danger">{formik.errors.subject}</div> : null}
        </div>
    </div>
</form>

但似乎 formik.dirty 未定义或不被视为真实(尽管对表格进行了更改)。

如何正确使用 dirty 道具来触发 Prompt

我不确定你有什么样的设置,但我创建了一个带有路由的 PoC,它有两个用于导航的选项卡(链接),我在带有 formik 表单的选项卡上使用 prompt组件。

import React from "react";
import { Prompt } from "react-router-dom";
import { useFormik } from "formik";

const MyForm = () => {
  const formik = useFormik({
    initialValues: {
      name: "",
      subject: ""
    },
    enableReinitialize: true,
    onSubmit: (values) => {
      alert(JSON.stringify(values, null, 2));
    },
    onChange: (e) => {
      console.log(e);
    }
  });

  return (
    <div>
      <Prompt
        when={!!formik.dirty}
        message={(location) =>
          `Are you sure you want to go to ${location.pathname}`
        }
      />
      <form id="myForm" onSubmit={formik.handleSubmit}>
        <div className="row">
          <div className="form-group">
            <label htmlFor="name">Name</label>
            <input
              id="name"
              type="text"
              onChange={formik.handleChange}
              value={formik.values.name}
              className="form-control"
              placeholder="Enter name"
            />
            {formik.errors.name ? (
              <div className="text-danger">{formik.errors.name}</div>
            ) : null}
          </div>
          <div className="form-group">
            <label htmlFor="subject">Subject</label>
            <input
              id="subject"
              type="text"
              onChange={formik.handleChange}
              value={formik.values.subject}
              className="form-control"
              placeholder="Email subject"
            />
            {formik.errors.subject ? (
              <div className="text-danger">{formik.errors.subject}</div>
            ) : null}
          </div>
          {formik.dirty && <button tye="submit">Save</button>}
        </div>
      </form>
    </div>
  );
};

export default MyForm;

看看 this codesandbox.