Typescript环境下结合React Hook Form使用MUI DatePicker组件报错求助
问题原因
Controller组件未接收校验规则:你定义了options属性存放校验规则,但没有传给Controller的rules属性,导致配置的必填等校验不生效。
- 丢弃了
field的ref属性:你在解构field的时候把ref单独拎出来丢弃,DatePicker需要通过ref绑定输入框实现焦点控制、弹窗定位等逻辑,缺失会导致功能异常。
- 丢弃了
- 自定义
renderInput写法错误:调用时传入的renderInput没有使用DatePicker注入的输入框参数,还额外传入了多余的register属性,使用Controller管理表单状态的场景下不需要手动调用register注册字段,会导致状态冲突。
- 自定义
- 未透传错误状态:组件接收了
error属性,但没有传递给最终渲染的TextField,无法显示错误提示样式和文案。
- 未透传错误状态:组件接收了
- 类型过滤问题:你的
ENOFieldOverrides类型中包含了renderInput字段,定义ENODateFieldProps时用Omit过滤ENOFieldOverrides会导致renderInput属性被组件拒绝接收,即使你调用时传入了也不会生效,这就是你截图报错的直接原因:DatePicker没有收到必填的renderInput属性。
- 类型过滤问题:你的
解决方案
第一步:修改ENODateField组件代码
import DatePicker, { DatePickerProps } from "@mui/lab/DatePicker"; import React from "react"; import { Control, Controller, FieldValues } from "react-hook-form"; import { ENOFieldOverrides, ENOFieldProps } from "./EnoFieldUtils"; import ENOTooltip from "./ENOTooltip"; import { makeStyles } from "@mui/styles"; import AdapterDateFns from "@mui/lab/AdapterDateFns"; import LocalizationProvider from "@mui/lab/LocalizationProvider"; import TextField from "@mui/material/TextField"; export interface ENODateFieldProps<T extends FieldValues> extends Omit<ENOFieldProps<T>, "register">, // 排除ENOFieldOverrides中的renderInput,避免过滤掉必填属性 Omit<DatePickerProps, Exclude<ENOFieldOverrides, "renderInput"> | "value" | "onChange"> { control: Control<T, object>; } const useStyles = makeStyles({ fullWidth: { width: "100%", }, }); export default function ENODateField<T extends FieldValues>({ name, control, options, error, tooltipText, ...rest }: ENODateFieldProps<T>) { const classes = useStyles(); return ( <ENOTooltip text={tooltipText}> <LocalizationProvider dateAdapter={AdapterDateFns}> <Controller name={name} control={control} // 把校验规则传给Controller的rules属性 rules={options} render={({ field }) => ( <DatePicker className={classes.fullWidth} // 完整透传field属性,包含ref、value、onChange等 {...field} {...rest} // 统一处理错误状态透传,优先使用用户自定义的renderInput renderInput={(params) => rest.renderInput ? ( rest.renderInput({ ...params, error: !!error, helperText: error?.message, }) ) : ( <TextField {...params} error={!!error} helperText={error?.message} /> ) } /> )} /> </LocalizationProvider> </ENOTooltip> ); }
第二步:修改调用代码
如果不需要自定义输入框,直接简化调用即可:
<DateField<ReceptionInvoice> label="Issue Date" control={control} name="invoiceDate" options={{ required: "This field is required", }} error={errors.invoiceDate} />
如果需要自定义TextField的其他属性,按如下写法传入renderInput即可:
<DateField<ReceptionInvoice> label="Issue Date" control={control} name="invoiceDate" options={{ required: "This field is required", }} error={errors.invoiceDate} renderInput={(params) => ( <TextField {...params} variant="outlined" size="small" // 其他自定义TextField属性 /> )} />
内容的提问来源于stack exchange,提问作者Akash
相关产品推荐
相关产品推荐

