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

如何使用React Hook Form和Material UI自定义TextField日期格式

自定义MUI TextField日期输入格式(结合react-hook-form)

我正在使用react-hook-form和@mui/material的TextField组件创建日期输入字段,当前日期显示为mm/dd/yyyy格式。我希望基于动态dateFormat属性自定义该格式,可取值如YYYY/MM/DD、MMMM DD, YYYY、DD MMMM YYYY等。尝试向TextField组件传递format属性但无效,请问如何实现所需的日期格式自定义?

原简化代码:

import { TextField } from "@mui/material";
import { Controller, useForm } from "react-hook-form";

export default function dateTimeValues(props) {
  // 原代码存在顺序错误:先解构后声明formContext,需修正
  const { control, formState } = formContext;

  const formContext = useForm({
    defaultValues: {
      dateTime: object?.dateTime?.slice(0, 10) || new Date().toISOString().slice(0, 10),
    },
  });

  useEffect(() => {
    reset({
      dateTime: object?.dateTime?.slice(0, 10) || new Date().toISOString().slice(0, 10),
    });
  }, [object, reset]);

  return (
    <Controller
      control={control}
      name="dateTime"
      render={({ field }) => {
        return (
          <TextField
            {...field}
            error={formState.errors.dateTime !== undefined}
            fullWidth
            helperText={formState.errors.dateTime && tGeneral("fieldRequired")}
            type="date"
            // I want to apply the dateFormat here
            format={dateFormat} // This doesn't work
          />
        );
      }}
      rules={{ required: true }}
    />
  );
}

方案一:使用MUI X DatePicker(推荐,更简洁)

MUI的@mui/x-date-pickers组件原生支持自定义日期格式,无需手动处理解析和格式化逻辑:

  1. 安装依赖:
npm install @mui/x-date-pickers @date-io/date-fns@v6 date-fns
  1. 修改组件代码:
import { TextField } from "@mui/material";
import { Controller, useForm } from "react-hook-form";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";

export default function dateTimeValues({ dateFormat, object, tGeneral }) {
  // 修正原代码顺序错误:先调用useForm再解构
  const { control, formState, reset } = useForm({
    defaultValues: {
      dateTime: object?.dateTime ? new Date(object.dateTime) : new Date(),
    },
  });

  useEffect(() => {
    reset({
      dateTime: object?.dateTime ? new Date(object.dateTime) : new Date(),
    });
  }, [object, reset]);

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <Controller
        control={control}
        name="dateTime"
        render={({ field: { onChange, value } }) => {
          return (
            <DatePicker
              value={value}
              onChange={onChange}
              renderInput={(params) => (
                <TextField
                  {...params}
                  error={formState.errors.dateTime !== undefined}
                  fullWidth
                  helperText={formState.errors.dateTime && tGeneral("fieldRequired")}
                />
              )}
              format={dateFormat} // 直接传入自定义格式即可生效
            />
          );
        }}
        rules={{ required: true }}
      />
    </LocalizationProvider>
  );
}

方案二:原生TextField + date-fns(手动处理格式化与解析)

如果不想引入MUI X组件,可将TextField设为type="text",用date-fns手动处理值的格式化和解析:

  1. 安装date-fns:
npm install date-fns
  1. 修改组件代码:
import { TextField } from "@mui/material";
import { Controller, useForm } from "react-hook-form";
import { format, parse, isValid } from "date-fns";

export default function dateTimeValues({ dateFormat, object, tGeneral }) {
  const { control, formState, reset } = useForm({
    defaultValues: {
      dateTime: object?.dateTime ? new Date(object.dateTime) : new Date(),
    },
  });

  useEffect(() => {
    reset({
      dateTime: object?.dateTime ? new Date(object.dateTime) : new Date(),
    });
  }, [object, reset]);

  return (
    <Controller
      control={control}
      name="dateTime"
      render={({ field: { onChange, value, name, ref } }) => {
        // 显示时格式化日期
        const displayValue = value ? format(value, dateFormat) : "";

        // 处理输入解析:将用户输入的字符串转为Date对象
        const handleChange = (e) => {
          const inputValue = e.target.value;
          if (!inputValue) {
            onChange(null);
            return;
          }
          const parsedDate = parse(inputValue, dateFormat, new Date());
          onChange(isValid(parsedDate) ? parsedDate : inputValue);
        };

        return (
          <TextField
            name={name}
            ref={ref}
            value={displayValue}
            onChange={handleChange}
            error={formState.errors.dateTime !== undefined}
            fullWidth
            helperText={formState.errors.dateTime && tGeneral("fieldRequired")}
            type="text" // 改为text类型,规避原生date输入的格式限制
          />
        );
      }}
      rules={{ 
        required: true,
        validate: (value) => isValid(value) || "请输入有效的日期"
      }}
    />
  );
}

关键说明

  • 原生HTML的input type="date"显示格式由浏览器系统locale决定,无法通过format属性自定义,因此必须改用type="text"或专用日期选择器组件。
  • 使用MUI X DatePicker时,格式字符串需符合date-fns规则(比如YYYY/MM/DD、MMMM dd, yyyy,注意小写dd对应日期、yyyy对应年份)。
  • 原代码中formContext的顺序错误会导致运行报错,需先调用useForm再解构control、formState等对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:40:54