React中FullCalendar无法显示Firebase来源事件的问题排查
问题:React中Firebase结合FullCalendar无法显示事件内容,仅显示日期标记
- 在React项目中使用Firebase配合FullCalendar展示用户事件,控制台能打印出所有事件数据,但日历上仅显示存在事件的蓝色日期标记,无法看到具体事件内容。移除async/await语法后问题仍未解决。
- 当前Firebase中的数据结构与之前正常运行的版本有差异,呈现嵌套状态。
当前代码(存在问题)
const DC = () => { const [events, setEvents] = useState([]); const [createEvent, setCreateEvent] = useState("") const [createDate, setCreateDate] = useState("") const [buttonDisabled, setButtonDisabled] = useState(false); console.log(events); const collectionRef = collection(db, 'calendar'); const getEvents = () => { const q = query(collectionRef); getDocs(q).then((eventsD) => { let eventsData = eventsD.docs.map((doc) => ({ ...doc.data(), id: doc.id })) setEvents(eventsData) }).catch((err) => { console.log(err) }) } useEffect(() => { getEvents() }, []) //Add Task Handler const submitTask = async (e) => { e.preventDefault(); try { await addDoc(collectionRef, { theEvent: createEvent, date: createDate, id: uuid(), timeStamp: serverTimestamp() }) setButtonDisabled(true); window.location.reload(); } catch (err) { console.log(err); } } return ( <> {/* Modal Button */} <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#reminderModal"> Add Reminder </button> <FullCalendar editable={true} selectable={true} events={events} headerToolbar={{ start: "today prev next", end: "dayGridMonth dayGridWeek dayGridDay", }} plugins={[daygridPlugin, interactionPlugin]} views={["dayGridMonth", "dayGridWeek", "dayGridDay"]} handleWindowResize={true} /> {/* Modal */} <div className="modal fade" id="reminderModal" tabindex="-1" aria-labelledby="reminderModalLabel" aria-hidden="true"> <div className="modal-dialog"> <form className="d-flex" onSubmit={submitTask}> <div className="modal-content"> <div className="modal-header"> <h1 className="modal-title fs-5" id="reminderModalLabel">Notify</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div className="modal-body"> <form> <input type="date" className="form-control" onChange={(e) => setCreateDate(e.target.value)} /> <input type="text" className="form-control" placeholder="State client's appointment details" onChange={(e) => setCreateEvent(e.target.value)} /> </form> </div> <div className="modal-footer"> <button type="button" className="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button type="submit" className="btn btn-primary" disabled={buttonDisabled}>Add Notifier</button> </div> </div> </form> </div> </div> </> ) }
旧版正常代码
const DC = () => { const [events, setEvents] = useState({ start: "", end: "", title: "", date: "", id: uuid(), }); const [buttonDisabled, setButtonDisabled] = useState(false); console.log(events); const handleInput = (e) => { const { name, value } = e.target; setEvents({ ...events, [name]: value }); } const collectionRef = collection(db, 'calendar'); const getEvents = () => { const q = query(collectionRef); getDocs(q).then((eventsD) => { let eventsData = eventsD.docs.map((doc) => ({ ...doc.data(), id: doc.id })) setEvents(eventsData) }).catch((err) => { console.log(err) }) } useEffect(() => { getEvents() }, []) //Add Task Handler const submitTask = async (e) => { e.preventDefault(); try { await addDoc(collectionRef, { ...events, timeStamp: serverTimestamp(), }) setButtonDisabled(true); window.location.reload(); } catch (err) { console.log(err); } } return ( <> <div className='dc'> {/* Modal Button */} <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#reminderModal"> Add Reminder </button> <FullCalendar editable={true} selectable={true} events={events} headerToolbar={{ start: "today prev next", end: "dayGridMonth dayGridWeek dayGridDay", }} plugins={[daygridPlugin, interactionPlugin]} views={["dayGridMonth", "dayGridWeek", "dayGridDay"]} handleWindowResize={true} /> </div> {/* Modal */} <div className="modal fade" id="reminderModal" tabindex="-1" aria-labelledby="reminderModalLabel" aria-hidden="true"> <div className="modal-dialog"> <form className="d-flex" onSubmit={submitTask}> <div className="modal-content"> <div className="modal-header"> <h1 className="modal-title fs-5" id="reminderModalLabel">Notify</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div className="modal-body"> <form> <input type="date" name="date" className="form-control" value={events.date} onChange={handleInput} /> <input type="text" name="title" className="form-control" placeholder="State client's appointment details" value={events.title} onChange={handleInput} /> </form> </div> <div className="modal-footer"> <button type="button" className="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button type="submit" className="btn btn-primary" disabled={buttonDisabled}>Add Notifier</button> </div> </div> </form> </div> </div> </> ) } export default DC
问题分析
核心问题是事件字段与FullCalendar的要求不匹配:
- FullCalendar必须读取事件对象的
title字段来显示事件内容,date/start字段来定位日期。 - 当前代码中,存入Firebase的事件内容字段是
theEvent,而非FullCalendar识别的title;旧版代码使用title字段,因此能正常显示。 - 日历能显示蓝色标记,说明
date字段被正确识别,但缺少title字段导致无法展示具体内容。
解决方案
两种修复方式任选其一即可:
方案1:修改数据映射,适配FullCalendar字段要求
在getEvents函数中,将Firebase返回的theEvent重命名为title:
const getEvents = () => { const q = query(collectionRef); getDocs(q).then((eventsD) => { let eventsData = eventsD.docs.map((doc) => ({ ...doc.data(), title: doc.data().theEvent, // 映射字段名 id: doc.id })) setEvents(eventsData) }).catch((err) => { console.log(err) }) }
方案2:修改添加事件的字段名,与旧版保持一致
在submitTask函数中,将theEvent改为title,直接存入符合要求的字段:
const submitTask = async (e) => { e.preventDefault(); try { await addDoc(collectionRef, { title: createEvent, // 替换字段名 date: createDate, id: uuid(), timeStamp: serverTimestamp() }) setButtonDisabled(true); window.location.reload(); } catch (err) { console.log(err); } }
额外修复:移除无效嵌套表单
当前Modal中嵌套了两层<form>标签,属于无效HTML结构,会导致表单行为异常,建议移除内层<form>:
<div className="modal-body"> {/* 移除内层<form>标签 */} <input type="date" className="form-control" onChange={(e) => setCreateDate(e.target.value)} /> <input type="text" className="form-control" placeholder="State client's appointment details" onChange={(e) => setCreateEvent(e.target.value)} /> </div>
内容的提问来源于stack exchange,提问作者Deezy
相关产品推荐
相关产品推荐

