Closed mauretto78 closed 3 years ago
Would you be able to post a runnable demonstration of the bug? Would really appreciate it because the time saved reproducing will be time spent fixing.
@acerix good morning, sorry for my late reply.
I reproduced here the bug:
https://codesandbox.io/s/white-dawn-knv4s?file=/src/App.js
As you can see, after dragging an element to the calendar, duplicates are generated.
I figured out that could be an issue related to bad state management.
I am so sorry for bothering you, I hope if you need more details don't hesitate to ask.
Thank you in advance
M,
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.
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
@arshaw Sorry for my late reply.
Many thanks. it worked like a charm!!
Hi all, and thanks a lot for the conversation so far. I've wrestled with this issue for two days now with no luck, so I have to ask for your help.
In the Codesandbox example from @arshaw start and end dates return as undefined when running handleEventReceive function. Therefore they will get saved to the state but do not get rendered to the calendar, as they do not have a valid start time.
When I changed the newEvent variable to grab a valid date (start: eventInfo.event.startStr), the event gets rendered to the calendar. However, it renders event as double, as it fetches one from the state and the one that get's dragged there.
The dragged event will get rendered to the calendar without the events source or even without the eventReceive handler. Is there a way to prevent this and only render the events from the state (or from another source? Or is there another way to prevent double rendering?
Here's a live demo and here's the code
I'm sure I've misunderstood this somehow, so all help is much appreciated!
Oh, and I noticed that more useful example would have the code and the live demo combined, so here's the StackBlitz of my example. @mauretto78 how did you solve this issue?
I just want to leave a note here, because someone might still stumble upon this problem (as I did). The solution might be more simple than in @arshaw's comment.
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
Passing an empty dependency array as a second argument to useEffect
should be already enough to make sure it's called only once. But the thing is, React intentionally invokes all the hooks twice in Strict Mode (i.e. in development). This is described in the docs. If you return a cleanup function from useEffect
, the result of the duplicate call will be immediately cleaned up, and no duplicate events will be created.
TLDR:
useEffect
to prevent re-initialization when the component is re-rendered;useEffect
callback, which destroys the Draggable
instance:// load external events
useEffect(() => {
let draggableEl = document.getElementById("external-events");
- new Draggable(draggableEl, {
+ const draggable = new Draggable(draggableEl, {
itemSelector: ".fc-event",
eventData: function (eventEl) {
...
}
});
+ return () => draggable.destroy();
- });
+ }, []);
@ameotoko that solution worked for me. Thanks!
same issue we are facing in javascript when we call method calender again in a different senerio please any one help us
function Calender()
{
var Draggable = FullCalendar.Draggable;
var containerEl = document.getElementById('accordion');
new Draggable(containerEl, {
itemSelector: '.fc-event',
eventData: function (eventEl)
{
return {
title: eventEl.innerText
};
},
zIndex: 999,
revert: true,
revertDuration: 0
});
var calendarEl = document.getElementById('Calender');
calendar = new FullCalendar.Calendar(calendarEl,
{
timeZone: 'UTC',
minTime: "9am",
maxTime: "9pm",
headerToolbar: {
left: 'prev,next',
center: 'title',
right: ''
},
aspectRatio: 1.5,
editable: false,
height: 580,
initialView: 'timeGridWeek',
resources: ResourcesArr,
events: EventsArr,
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
droppable: true,
drop: function (dropInfo) {
},
eventReceive: function (info)
{
},
eventClick: function (calEvent, jsEvent, view) {
},
});
calendar.render();
}
I use JavaScript style to create the draggable in an useEffect callback:
new Draggable(containerEl, {
itemSelector: '.item-class',
eventData: function(eventEl) {
return {
title: eventEl.innerText,
duration: '02:00'
};
}
});
And it proves me wrong since, thanks for the answers above. I realize the draggable need to be created per event:
useEffect(() => {
let draggable = new Draggable(elRef.current, {
eventData: function () {
return { ...event, create: true };
}
});
// a cleanup function
return () => draggable.destroy();
});
Otherwise, multiple draggable will be created for one external event. And when dragging this external event, it will generate multiple events on the fullcalendar.
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:
And this is the calendar (notice that I passed events and event handling functions from the root component via props):
And finally, this is my root component:
Now, when you drag elements:
handleEventReceive
function is called ONE time and ONE event is added to state and to the calendar;handleEventReceive
function is called TWICE and TWO events are added to state and to the calendar;handleEventReceive
function is called FOUR TIMES and FOUR events are added to state and to the calendar;I already tried with
created: false
inEventList
and usingdrop
instead ofeventReceive
inCalendar
, but the result is the same.I am sorry for bothering you, and I hope this can help someone.
Many thanks in advance :)