question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Dragging external events generates duplicates on calendar

See original GitHub issue

IMPORTANT PREMISE:

I don’t understand if is a duplicate of this, in case delete the issue:

https://github.com/fullcalendar/fullcalendar/issues/7067

DESCRIPTION OF BUG

When dragging an external event to the calendar, one or more duplicates of the event are generated.

STEP TO REPRODUCE (WITH SAMPLE CODE)

I have a root component called PageCalendar. This component contains a list of draggable events and the calendar.

This is my event list:

// EventList.js

const EventList = (props) => {

    useEffect(() => {
        let draggableEl = document.getElementById("external-events");
        new Draggable(draggableEl, {
            itemSelector: ".fc-event",
            eventData: function(eventEl) {
                let id = eventEl.dataset.id;
                let title = eventEl.getAttribute("title");
                let color = eventEl.dataset.color;
                let custom = eventEl.dataset.custom;

                return {
                    id: id,
                    title: title,
                    color: color,
                    custom: custom,
                    create: true
                };
            }
        });
    });

  // other stuff

And this is the calendar (notice that I passed events and event handling functions from the root component via props):

// Calendar.js

const Calendar = (props) => {

    // other stuff

    return (
        <>
            <FullCalendar
                locale={itLocale}
                plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
                headerToolbar={{
                    left: 'prev,next today',
                    center: 'title',
                    right: 'dayGridMonth,timeGridWeek,timeGridDay'
                }}
                initialView='dayGridMonth'
                editable={true}
                selectable={true}
                selectMirror={true}
                dayMaxEvents={true}
                weekends={props.weekendsVisible}
                events={props.events}
                droppable={true}
                eventContent={renderEventContent} 
                eventClick={handleEventClick}
                eventReceive={props.handleEventReceive}
            />
        </>
    );
};

export default Calendar;

And finally, this is my root component:

// PageCalendar.js

const PageCalendar = () => {

    // initial state
    const [state, setState] = useState({
        weekendsVisible: true,
        calendarEvents: getEvents(),
        externalEvents: externalEvents(),
        filterEvents: {
            cat: null,
            id: null
        }
    });

   const handleEventReceive = (eventInfo) => {
        const newEvent = {
            id: eventInfo.draggedEl.getAttribute("data-id"),
            title: eventInfo.draggedEl.getAttribute("title"),
            color: eventInfo.draggedEl.getAttribute("data-color"),
            start: eventInfo.date,
            end: eventInfo.date,
            custom: eventInfo.draggedEl.getAttribute("data-custom")
        };

        setState(state => {
            return {
                ...state,
                calendarEvents:state.calendarEvents.concat(newEvent)
            };
        });
    };

 return (
        <>
            <Header
                addEvent={handleAddExternalEvent}
                weekendsVisible={state.weekendsVisible}
                filterEvents={handleFilterCalendarEvents}
                weekendsToggle={handleWeekendsToggle}
            />
            <CCard>
                <CCardBody>
                    <CRow>
                        <CCol md="2">
                            <EventList
                                deleteEvent={handleDeleteEvent}
                                externalEvents={state.externalEvents}
                                filterEvents={handleFilterEvents}
                            />
                        </CCol>
                        <CCol md="10">
                            <Calendar
                                events={state.calendarEvents}
                                handleEventReceive={handleEventReceive}
                                weekendsVisible={state.weekendsVisible}
                            />
                        </CCol>
                    </CRow>
                </CCardBody>
            </CCard>
        </>
    );
};

export default PageCalendar;

Now, when you drag elements:

  • for the first event dragged handleEventReceive function is called ONE time and ONE event is added to state and to the calendar;
  • for the second event dragged handleEventReceive function is called TWICE and TWO events are added to state and to the calendar;
  • for the third event dragged handleEventReceive function is called FOUR TIMES and FOUR events are added to state and to the calendar;
  • etc…

I already tried with created: false in EventList and using drop instead of eventReceive in Calendar, but the result is the same.

I am sorry for bothering you, and I hope this can help someone.

Many thanks in advance 😃

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
arshawcommented, Jan 16, 2021

The problem is that your useEffect callback is being called whenever there is any state change to your root component, subsequently reinitializing the Draggable without destroying it. These duplicate initializations on the same element result in multiple events being added each time.

The solution is to make sure new Draggable is only called once per external element. Here is a solution that involves moving useEffect within a subcomponent, useRef, and memo (to prevent unnecessary rerendering).

https://codesandbox.io/s/fullcalendar-react-draggable-forked-ehr0h?file=/src/App.js

1reaction
acerixcommented, Dec 30, 2020

Thanks for the demo, it does seem like a bug, liekly related to the issue you mentioned but I’m not sure it’s a duplicate.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Fix duplicate events in fullcalendar in React - Stack Overflow
when a new external event is dropped onto the calendar, FullCalendar creates a new event and adds it to its own internal event...
Read more >
If you have duplicate events on your iCloud Calendar
If you see duplicate calendars or events on your iPhone, iPad, iPod touch, Mac, or PC after you set up iCloud Calendar, follow...
Read more >
External Event Dragging - Docs - FullCalendar
It's possible to take elements that live outside of a calendar and make them drag-and-droppable. When they are dropped on a specific date...
Read more >
Duplicating pages and content - Squarespace Help Center
Duplicating is a great way to use an existing page, section, block, post, product, event, or video as a starting point for new...
Read more >
Customization Options for Events and Calendars
In Salesforce Classic, on contact and lead list views, let users schedule events by dragging a contact or lead onto the calendar. You...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found