使用Luxon搭配MUI DatePicker时出现Cannot read 'equals'未定义属性错误
解决MUI DatePicker搭配Luxon时的TypeError: Cannot read properties of undefined (reading 'equals')
这个错误的核心原因是AdapterLuxon的setTimezone方法尝试调用一个undefined对象的equals方法,通常是由于传递给DatePicker的value不符合预期(既不是有效的Luxon DateTime对象,也不是null),或是版本兼容性、时区配置冲突导致的。以下是具体修复方案:
1. 优化日期值处理,确保类型合规
你的代码中重复调用DateTime.fromISO,且存在潜在的undefined传递风险。改用useMemo缓存处理后的日期值,确保仅返回null或有效DateTime对象:
// 在组件内部添加缓存逻辑 const returnDateValue = React.useMemo(() => { if (!formik.values.returnDate) return null; const dateTime = DateTime.fromISO(formik.values.returnDate); return dateTime.isValid ? dateTime : null; }, [formik.values.returnDate]);
然后将DatePicker的value替换为该变量:
value={returnDateValue}
2. 检查版本兼容性
不同版本的@mui/x-date-pickers对Luxon版本有明确要求:
- 若使用
@mui/x-date-pickers v6,需搭配Luxon >= 3.0.0 - 若使用
@mui/x-date-pickers v5,建议使用Luxon ^2.0.0
通过以下命令调整版本:
# 适配MUI X v6:升级到最新Luxon npm install luxon@latest # 适配MUI X v5:安装2.x版本 npm install luxon@2.x
3. 统一时区配置
你全局设置了Settings.defaultZone = 'utc',需在LocalizationProvider中明确指定时区,避免组件内部逻辑冲突:
<LocalizationProvider dateAdapter={AdapterLuxon} adapterLocale="en-GB" timezone="utc" >
4. 规范Formik初始值
确保formik.values.returnDate的初始值为null而非undefined,避免潜在的类型异常:
// 示例Formik初始值配置 const initialValues = { returnDate: null, // 其他表单字段... };
完整优化后的代码示例
import React, { useMemo } from 'react'; import { TextField } from '@mui/material'; import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterLuxon } from '@mui/x-date-pickers/AdapterLuxon'; import { Settings, DateTime } from 'luxon'; // 全局配置Luxon Settings.defaultLocale = 'en-GB'; Settings.defaultZone = 'utc'; function FlightDetails({ formik }) { const returnDateValue = useMemo(() => { if (!formik.values.returnDate) return null; const dateTime = DateTime.fromISO(formik.values.returnDate); return dateTime.isValid ? dateTime : null; }, [formik.values.returnDate]); return ( <LocalizationProvider dateAdapter={AdapterLuxon} adapterLocale="en-GB" timezone="utc" > <DatePicker label="Return Date" name="returnDate" value={returnDateValue} onChange={(newValue) => { formik.setFieldValue('returnDate', newValue ? newValue.toISO() : null); }} onBlur={() => formik.setFieldTouched('returnDate')} renderInput={(params) => ( <TextField {...params} error={formik.touched.returnDate && Boolean(formik.errors.returnDate)} helperText={formik.touched.returnDate ? formik.errors.returnDate : null} /> )} inputFormat="dd/MM/yyyy" fullWidth /> </LocalizationProvider> ); } export default FlightDetails;
内容的提问来源于stack exchange,提问作者grimfate
相关产品推荐
相关产品推荐

