React中FullCalendar接收拖拽事件时重复创建多实例问题
日历拖拽创建事件重复生成问题
在React中实现了日历功能,支持从侧边栏容器拖拽用户到日历上创建预约事件。事件更新(调整大小、拖拽移动)功能正常,但触发eventReceive事件时,会重复创建多个仅ID不同的相同事件:初始生成3个,之后依次递增为4个、5个;若编辑已创建的事件,下次触发eventReceive时生成的实例数量会额外增加编辑次数,比如原本应生成4个,编辑后会生成5个,后续持续递增。
日历组件代码
const Calendar = ({ ToSaveEvents, uid, ToSaveEventsList }: any) => { const [events, setEvents] = useState<TrueCalendarEvent[]>([]) const CalRef = useRef<FullCalendar>(null) useEffect(() => { const db = getDatabase(app) const unsub = onValue(ref(db, `users/${uid}/CalendarEvents`), (snapshot) => { ///获取已保存的事件用于展示或检测变更 } }) return () => { unsub() } }, []) const InCalendarUpdate = useCallback((info: EventResizeDoneArg | EventDropArg) => { const { event } = info if (events.find(ev => ev.id === event.id)) { const db = getDatabase(app) remove(ref(db, `users/${uid}/CalendarEvents/${event.id}`)) ToSaveEvents((prevEvents: any) => { return [...prevEvents, event] }) } const updatedEvent = { title: info.event.title, start: info.event.start ? info.event.start.toISOString() : null, end: info.event.end ? info.event.end.toISOString() : null, color: "#D7C627" } ToSaveEvents((prevEvents: any) => { return prevEvents.map((ev: TrueCalendarEvent) => { const { extendedProps, ...lastev } = ev return ev.id == event.id ? { ...lastev, ...updatedEvent, extendedProps: { ...extendedProps, lastevent: (extendedProps.lastevent == null ? lastev : extendedProps.lastevent) } } : ev }) }) info.event.remove(); },[]) const handleEventReceive = useCallback((info: EventReceiveArg) => { const defaultEndTime = new Date(info.event.start!.getTime() + 60 * 60 * 1000).toISOString() const newEvent = { id: info.event.id, title: info.event.title, start: info.event.start ? info.event.start.toISOString() : null, end: info.event.end ? info.event.end.toISOString() : defaultEndTime, color: "#D7C627", extendedProps: { lastevent: null, ToID: info.event.extendedProps.ToID } }; ToSaveEvents((prevState: any) => { return [...prevState, newEvent] }) info.event.remove(); },[]) useEffect(() => { if (CalRef.current) { const Calapi = CalRef.current.getApi() Calapi.setOption("eventReceive", undefined) Calapi.setOption("eventResize", undefined) Calapi.setOption("eventDrop", undefined) Calapi.setOption("eventReceive", handleEventReceive) Calapi.setOption("eventResize", InCalendarUpdate) Calapi.setOption("eventDrop", InCalendarUpdate) } }, [InCalendarUpdate,handleEventReceive]) return ( <FullCalendar plugins={[dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin]} initialView="timeGridDay" events={[...events, ...ToSaveEventsList]} editable={true} droppable={true} headerToolbar={{ left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth' }} ref={CalRef} /> ); };
侧边栏组件代码
const SidebarDoctor = ({ uid }: any) => { const [users, changeUsers] = useState<any>([]) const [doctorfirstname, changedoctorfirstname] = useState<string>("") const [doctorlastname, changedoctorlastname] = useState<string>("") useEffect(() => { const db = getDatabase(app) const fetchname = async () => { ///调用Firebase数据库获取数据 } fetchname() const unsub = onValue(ref(db, `users/${uid}/notifs`), async (snapshot: any) => { ///调用Firebase数据库获取数据 }) return () => { unsub() } }, []) const UsersRef = useRef(null) const DragableElements = UsersRef.current if (DragableElements) { new Draggable(DragableElements, { itemSelector: '.user-item', eventData(eventEl) { const id = uuidv4() const firstlastnamePacient = eventEl.dataset.firstname + " " + eventEl.dataset.lastname const firstlastnameDoctor = doctorfirstname + " " + doctorlastname const lastevent: CalendarEvent = { id: "", title: "", start: "", end: "", color: "" } const ToID = eventEl.dataset.id return { id, title: firstlastnamePacient + " appointment to " + firstlastnameDoctor, extendedProps: { lastevent, ToID: ToID } }; }, }); } return ( <div className="sidebar"> <div id="users-list" ref={UsersRef}> <h4>Users</h4> {users.map((user: any) => { return <div key={uuidv4()} data-id={user.id} style={{ marginBottom: '5px' }} className="user-item fc-event" > {user.firstname + " " + user.lastname} </div> })} </div> </div>) }
内容的提问来源于stack exchange,提问作者No0bYebY
相关产品推荐
相关产品推荐

