React、Formik、Yup:如何在使用日历选择器时注册触摸

React, Formik, Yup: How to register touch when using calendar picker

我对这三种技术都不熟悉并搜索了答案,但找不到。注意:我简化了文件,以便在您阅读时更容易解析,希望我没有删除任何对调试重要的内容。

当用户使用日历选择器单击 select 日期时,我想让我的表单注册为已触及。目前我可以在 helperText 中显示错误,但它不会像用户在字段中单击时那样改变表单的样式,就好像他们打算自己输入一样。

import React, { FC, useRef } from "react";
import { Formik, Form, Field } from "formik";
import { KeyboardDatePicker } from "formik-material-ui-pickers";
import * as Yup from "yup";
import moment from "moment";
import { ReportConfig } from "../ReportConfig";

export type DProps = {
  type: Type | null,
  currentConfig: ReportConfig | null,
};

export const Dialog: FC<DProps> = ({ currentConfig }) => {
  const form: any = useRef(null); // Reference to formik form

  let initialValues = {
    periodStart: moment(currentConfig?.periodStart),
    periodEnd: moment(currentConfig?.periodEnd),
  };

  return (
    <Formik
      innerRef={form}
      initialValues={initialValues}
      validationSchema={Yup.object().shape({
        periodStart: Yup.date()
          .typeError("Enter a valid date.")
          .max(Yup.ref("periodEnd"), "Must be before End.")
          .required("Required"),
        periodEnd: Yup.date()
          .typeError("Enter a valid date.")
          .min(Yup.ref("periodStart"), "Must be after Start.")
          .required("Required"),
      })}
    >
      {({ values, errors, touched, handleBlur }) => (
        <Form>
          <Field
            variant="inline"
            autoOk
            name={"periodStart"}
            value={values.periodStart}
            label="Start Date"
            inputVariant="outlined"
            component={KeyboardDatePicker}
            format="MM/DD/YYYY"
            onBlur={handleBlur}
            error={touched.periodEnd && errors.periodStart !== undefined}
            helperText={errors.periodStart}
          />
          <Field
            variant="inline"
            autoOk
            name={"periodEnd"}
            value={values.periodEnd}
            label="End Date"
            inputVariant="outlined"
            component={KeyboardDatePicker}
            format="MM/DD/YYYY"
            onBlur={handleBlur}
            error={touched.periodEnd && errors.periodEnd !== undefined}
            helperText={errors.periodEnd}
          />
        </Form>
      )}
    </Formik>
  );
};

对比

我明白了。您必须添加 setFieldTouched 并为其提供一个将 touched 设置为 true 的匿名函数。

import React, { FC, useRef } from "react";
import { Formik, Form, Field } from "formik";
import { KeyboardDatePicker } from "formik-material-ui-pickers";
import * as Yup from "yup";
import moment from "moment";
import { ReportConfig } from "../ReportConfig";

export type DProps = {
  type: Type | null,
  currentConfig: ReportConfig | null,
};

export const Dialog: FC<DProps> = ({ currentConfig }) => {
  const form: any = useRef(null); // Reference to formik form

  let initialValues = {
    periodStart: moment(currentConfig?.periodStart),
    periodEnd: moment(currentConfig?.periodEnd),
  };

  return (
    <Formik
      innerRef={form}
      initialValues={initialValues}
      validationSchema={Yup.object().shape({
        periodStart: Yup.date()
          .typeError("Enter a valid date.")
          .max(Yup.ref("periodEnd"), "Must be before End.")
          .required("Required"),
        periodEnd: Yup.date()
          .typeError("Enter a valid date.")
          .min(Yup.ref("periodStart"), "Must be after Start.")
          .required("Required"),
      })}
    >
      {({ values, errors, touched, handleBlur, setFieldTouched }) => (
        <Form>
          <Field
            variant="inline"
            autoOk
            name={"periodStart"}
            value={values.periodStart}
            label="Start Date"
            inputVariant="outlined"
            component={KeyboardDatePicker}
            format="MM/DD/YYYY"
            onBlur={handleBlur}
            error={touched.periodEnd && errors.periodStart !== undefined}
            helperText={errors.periodStart}
            onClick={() => setFieldTouched("periodStart", true)}
          />
          <Field
            variant="inline"
            autoOk
            name={"periodEnd"}
            value={values.periodEnd}
            label="End Date"
            inputVariant="outlined"
            component={KeyboardDatePicker}
            format="MM/DD/YYYY"
            onBlur={handleBlur}
            error={touched.periodEnd && errors.periodEnd !== undefined}
            helperText={errors.periodEnd}
            onClick={() => setFieldTouched("periodEnd", true)}
          />
        </Form>
      )}
    </Formik>
  );
};