如何使用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组件原生支持自定义日期格式,无需手动处理解析和格式化逻辑:
- 安装依赖:
npm install @mui/x-date-pickers @date-io/date-fns@v6 date-fns
- 修改组件代码:
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手动处理值的格式化和解析:
- 安装date-fns:
npm install date-fns
- 修改组件代码:
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
相关产品推荐
相关产品推荐

