React+Material UI表单Date/Time组件无法获取name值报错求助
问题排查:Material UI Date/TimePicker 无法获取name值导致表单提交错误
问题描述
使用React+Material UI构建表单时,添加DatePicker和TimePicker组件后,提交表单出现错误:TypeError: Cannot read properties of undefined (reading 'name'),仅日期和时间字段存在该问题。
错误原因
- 回调参数不兼容:Material UI的DatePicker/TimePicker的
onChange回调直接返回选中的日期/时间值(Dayjs实例),而非标准DOM事件对象,因此原有handleReservationChange函数中访问event.target.name会触发undefined报错。 - 无效属性传递:给
LocalizationProvider添加name属性无意义,该组件不会将name传递给内部输入控件。
解决方案
1. 修改事件处理函数,兼容两种输入类型
调整handleReservationChange,使其同时支持普通输入框的DOM事件和Date/TimePicker的数值回调:
function handleReservationChange(field, value) { // 处理普通输入框的DOM事件 if (typeof field === 'object' && field.target) { const { name, value: inputValue } = field.target; setReservationData(prev => ({ ...prev, [name]: inputValue })); } else { // 处理Date/TimePicker的数值(转换为ISO字符串方便后端处理) const formattedValue = value ? value.toISOString() : ''; setReservationData(prev => ({ ...prev, [field]: formattedValue })); } }
2. 调整DatePicker/TimePicker的onChange绑定
给Date/TimePicker明确传递字段名,替换原有的onChange={handleReservationChange}:
// DatePicker部分 <FormControl> <LocalizationProvider dateAdapter={AdapterDayjs} fullWidth> <DatePicker label="Date" value={reservationData.date} onChange={(value) => handleReservationChange('date', value)} renderInput={(params) => <TextField {...params} name="date" />} /> </LocalizationProvider> </FormControl> // TimePicker部分 <FormControl> <LocalizationProvider dateAdapter={AdapterDayjs}> <TimePicker label="Time" value={reservationData.time} onChange={(value) => handleReservationChange('time', value)} renderInput={(params) => <TextField {...params} name="time" />} /> </LocalizationProvider> </FormControl>
3. 可选:提交时统一处理日期格式
如果不想在事件处理中转换格式,也可以在提交表单时统一将Dayjs对象转为字符串:
function handleReservationSubmit(event){ event.preventDefault(); const newReservation={ ...reservationData, // 转换Dayjs对象为ISO字符串 date: reservationData.date ? reservationData.date.toISOString() : '', time: reservationData.time ? reservationData.time.toISOString() : '', restaurant_id: params.id, user_id: user.id, }; // 后续fetch逻辑不变 }
完整修改后的代码片段
function ReservationForm(){ const navigate = useNavigate(); const params = useParams(); const {user}=useContext(Cont) const[reservationData,setReservationData]=useState({ name:"", date:"", time:"", num:"", contact:"", occasion:"", }); // 修改后的事件处理函数 function handleReservationChange(field, value) { if (typeof field === 'object' && field.target) { const { name, value: inputValue } = field.target; setReservationData(prev => ({ ...prev, [name]: inputValue })); } else { const formattedValue = value ? value.toISOString() : ''; setReservationData(prev => ({ ...prev, [field]: formattedValue })); } } function handleReservationSubmit(event){ event.preventDefault(); const newReservation={ ...reservationData, restaurant_id: params.id, user_id: user.id, }; fetch(`/reservations`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(newReservation), }) .then((r) => r.json()) .then(() => { setReservationData({ name:"", date:"", time:"", num:"", contact:"", occasion:"", }) }); navigate("/myreservations"); } return( <> <Box component="form" sx={{ "& > :not(style)": { m: 1 }, }} noValidate autoComplete="off" onSubmit={handleReservationSubmit} > <h1 className="editheadings">Reserve 🍽️</h1> <FormControl className="inputstyle"> <InputLabel htmlFor="component-outlined">Name</InputLabel> <OutlinedInput type="text" name="name" id="name" value={reservationData.name} onChange={handleReservationChange} label="Name" /> </FormControl> <br /> {/* 修改后的DatePicker */} <FormControl> <LocalizationProvider dateAdapter={AdapterDayjs} fullWidth> <DatePicker label="Date" value={reservationData.date} onChange={(value) => handleReservationChange('date', value)} renderInput={(params) => <TextField {...params} name="date" />} /> </LocalizationProvider> </FormControl> {/* 修改后的TimePicker */} <FormControl> <LocalizationProvider dateAdapter={AdapterDayjs}> <TimePicker label="Time" value={reservationData.time} onChange={(value) => handleReservationChange('time', value)} renderInput={(params) => <TextField {...params} name="time" />} /> </LocalizationProvider> </FormControl> <br /> <FormControl className="inputstyle"> <InputLabel htmlFor="component-outlined">No. of Guests</InputLabel> <OutlinedInput type="number" name="num" value={reservationData.num} onChange={handleReservationChange} /> </FormControl> <br /> <FormControl className="inputstyle"> <InputLabel htmlFor="component-outlined">Contact</InputLabel> <OutlinedInput type="tel" name="contact" value={reservationData.contact} onChange={handleReservationChange} placeholder="contact" /> </FormControl> <br /> <FormControl className="inputstyle"> <InputLabel htmlFor="component-outlined">Occasion</InputLabel> <OutlinedInput type="text" name="occasion" value={reservationData.occasion} onChange={handleReservationChange} /> </FormControl> <Stack paddingLeft={15} direction="row" id="loginbutton"> <ColorButton variant="contained" type="submit"> {" "} Update Reservation </ColorButton> </Stack> </Box> </> ) } export default ReservationForm;
内容的提问来源于stack exchange,提问作者codertraveller
相关产品推荐
相关产品推荐

