Next.js向Firebase推送状态时遇错:date状态未定义
问题分析与解决方案
我需要将react-schedule-meeting组件选中的日期存入state,再推送到Firebase。但从Firebase获取时间戳格式的日期并传入日历组件时出现报错,按官方示例方式获取日期则一切正常,仅date状态返回undefined。
相关代码
日历组件代码
const [date, setDate] = useState() <ScheduleMeeting primaryColor={calendarPrimary} eventDurationInMinutes={30} borderRadius={calendarRadius} startTimeListStyle={timeStyle} selectedDateMonthTitleFormatString="cccc, LLLL do" availableTimeslots={timestamps} onStartTimeSelect={setDate} />
推送至Firebase的代码
const handleCreate = () => { const db = getFirestore(app) if (router.query.calendar) { console.log('date ', date) setDoc(doc(db, 'links', router.query.calendar, 'meetings', meetingname), { timeValue: timeValue, name: meetingname, email: meetingemail, date: date }).then(notify) } }
从Firebase获取数据的代码
if (docSnap.exists()) { setSchedule(docSnap.data()) console.log(docSnap.data()['schedule']) for (var i in docSnap.data()['schedule']) { setTimestamps((array) => [...array, { startTime: new Date(docSnap.data()['schedule'][0]['start']['seconds'] * 1000), endTime: new Date(docSnap.data()['schedule'][0]['end']['seconds'] * 1000) }]); } }
监听状态变化的代码(用于模态表单)
useEffect(() =>{ if(date){ setOpened(true) } }, [date])
问题根源
- Firebase数据读取逻辑错误:循环中始终取
schedule[0],导致timestamps数组里全是重复的同一个时间段,完全没有正确遍历所有日程数据;同时使用var会引发变量提升问题,导致循环逻辑异常。 - 日期状态初始化不明确:
date初始值为undefined,如果日历组件因数据格式错误无法触发onStartTimeSelect事件,date会一直保持undefined状态。 - 组件数据格式不匹配:日历组件的
availableTimeslots要求传入格式正确的时间段数组,错误的timestamps数据会导致组件内部报错,进而无法正常触发日期选择事件。
修复方案
1. 修正Firebase数据读取逻辑
把循环中的固定索引0改为当前循环变量,并替换var为let,同时用更高效的map方法生成数组:
if (docSnap.exists()) { const scheduleData = docSnap.data()['schedule']; setSchedule(scheduleData); // 转换为组件需要的时间段格式 const newTimestamps = scheduleData.map(item => ({ startTime: new Date(item.start.seconds * 1000), endTime: new Date(item.end.seconds * 1000) })); setTimestamps(newTimestamps); }
2. 初始化date状态
给date设置明确的初始值,避免undefined引发的判断问题:
const [date, setDate] = useState(null)
3. 校验组件数据格式
添加数据校验,过滤无效的时间段,确保传入组件的timestamps格式完全符合要求:
if (docSnap.exists()) { const scheduleData = docSnap.data()['schedule']; setSchedule(scheduleData); const newTimestamps = scheduleData .map(item => { // 校验时间戳是否有效 const hasValidTime = item.start?.seconds && item.end?.seconds; if (!hasValidTime) return null; return { startTime: new Date(item.start.seconds * 1000), endTime: new Date(item.end.seconds * 1000) }; }) .filter(Boolean); // 过滤无效项 setTimestamps(newTimestamps); }
4. 排查组件报错
根据报错信息(无法读取undefined的属性),确认availableTimeslots的结构与官方示例完全一致,每个时间段的startTime和endTime必须是有效的Date对象。
内容的提问来源于stack exchange,提问作者like who
相关产品推荐
相关产品推荐

