You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Material UI DatePicker结合Formik时遇TypeError: date.isBefore is not a function求助

解决Material UI DatePicker + Formik的「TypeError: date.isBefore is not a function」错误

错误根源

  1. 类型不匹配:使用AdapterDayjs时,Material UI DatePicker要求value必须是dayjs对象,但你设置的初始值是原生new Date(),导致组件内部调用dayjs的isBefore方法时,因值为原生Date对象而报错(原生Date没有该方法)。
  2. onChange逻辑不兼容:Formik的handleChange是为原生表单元素设计的,它期望接收Event对象并读取event.target.value,但DatePicker的onChange直接返回dayjs日期对象,直接使用会导致Formik无法正确更新values。

修复步骤

1. 导入dayjs依赖

取消注释dayjs的导入语句,因为AdapterDayjs依赖dayjs库:

import dayjs from 'dayjs';

2. 统一日期值类型

将Formik的initialValues中dob改为dayjs(),确保和DatePicker期望的类型一致:

initialValues={{ userName: "", dob: dayjs() }}

3. 适配DatePicker的onChange逻辑

使用Formik提供的setFieldValue方法手动更新dob字段,替代原生的handleChange:

<DatePicker
  label="Date of birth"
  value={values.dob}
  onChange={(newValue) => setFieldValue("dob", newValue)}
  onBlur={handleBlur}
  name="dob"
  error={Boolean(touched.dob) && Boolean(errors.dob)}
  helperText={touched.dob && errors.dob}
/>

4. 调整Yup验证规则

改用yup.mixed().test()验证dayjs对象的有效性,替代原有的yup.date():

const userSchema = yup.object().shape({
  userName: yup.string().required("required"),
  dob: yup.mixed().test(
    "is-valid-date",
    "required",
    (value) => dayjs.isDayjs(value) && value.isValid()
  )
});

完整修复代码

import React from "react";
import { Formik } from "formik";
import { Box, Button, Paper, Stack, TextField, styled } from "@mui/material";
import { Lock } from "@mui/icons-material";
import * as yup from "yup";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import dayjs from 'dayjs';

const LoginPage = () => {
  const StyledPaper = styled(Paper)({
    width: "500px",
    borderRadius: "10px",
    backgroundColor: "white",
    padding: "30px",
    position: "absolute",
    top: "50%",
    left: "50%",
    transform: "translate(-50%, -50%)"
  });

  const userSchema = yup.object().shape({
    userName: yup.string().required("required"),
    dob: yup.mixed().test(
      "is-valid-date",
      "required",
      (value) => dayjs.isDayjs(value) && value.isValid()
    )
  });

  const handleFormSubmit = (values, onSubmitProps) => {
    // 如需转换为原生Date对象,可调用dayjs的toDate()方法
    const dobAsNativeDate = values.dob.toDate();
    console.log("表单值:", values);
    console.log("出生日期(原生Date):", dobAsNativeDate);
  };

  return (
    <Formik
      onSubmit={handleFormSubmit}
      initialValues={{ userName: "", dob: dayjs() }}
      validationSchema={userSchema}
    >
      {({ values, errors, touched, handleBlur, handleSubmit, setFieldValue }) => (
        <form onSubmit={handleSubmit}>
          <StyledPaper elevation={3}>
            <Box
              sx={{
                display: "flex",
                justifyContent: "center",
                alignItems: "center",
                margin: "10px"
              }}
            >
              <Lock color="primary" fontSize="large" />
            </Box>
            <Stack direction="column" gap={2}>
              <TextField
                label="User Name"
                value={values.userName}
                onChange={handleChange}
                onBlur={handleBlur}
                name="userName"
                error={Boolean(touched.userName) && Boolean(errors.userName)}
                helperText={touched.userName && errors.userName}
              />

              <LocalizationProvider dateAdapter={AdapterDayjs}>
                <DatePicker
                  label="Date of birth"
                  value={values.dob}
                  onChange={(newValue) => setFieldValue("dob", newValue)}
                  onBlur={handleBlur}
                  name="dob"
                  error={Boolean(touched.dob) && Boolean(errors.dob)}
                  helperText={touched.dob && errors.dob}
                />
              </LocalizationProvider>

              <Button variant="contained" type="submit">
                Submit
              </Button>
            </Stack>
          </StyledPaper>
        </form>
      )}
    </Formik>
  );
};

export default LoginPage;

关键说明

  • 所有与DatePicker交互的日期值必须保持为dayjs对象,避免类型转换错误。
  • 使用setFieldValue是Formik中手动更新字段值的标准方式,适合处理非原生表单组件的回调。
  • 在提交表单时,可通过dayjs.toDate()将dayjs对象转换为原生Date对象,方便后续业务处理。

内容的提问来源于stack exchange,提问作者Priyanka Chaurasia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:15:24