Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FullCalendar shows events duplicated on modification #7071

Closed
Phibedy opened this issue Aug 28, 2020 · 20 comments
Closed

FullCalendar shows events duplicated on modification #7071

Phibedy opened this issue Aug 28, 2020 · 20 comments

Comments

@Phibedy
Copy link

Phibedy commented Aug 28, 2020

Reduced Test Case

https://codesandbox.io/s/zealous-jepsen-190d2?file=/src/DemoApp.jsx

Bug Description

If I press down on an event, move it, release the mouse button, press the mouse button again,
-> can drag a copy of the event

Screenshots

From the minimal working example
event_duplication

In the app, with some more hooks/delay it works close to every time. The title is rendered as the title is calculated in eventDidMount
duplication_from_app

@Phibedy
Copy link
Author

Phibedy commented Aug 28, 2020

Maybe it is because the calendar thinks it owns the events and creates new one. I also tried to implement 2 from fullcalendar/fullcalendar-react#65

@Phibedy
Copy link
Author

Phibedy commented Aug 28, 2020

This is similar to fullcalendar/fullcalendar-react#47

@Phibedy
Copy link
Author

Phibedy commented Aug 28, 2020

Disabling FullCalendar own event storage would solve this problem: #5150

@acerix
Copy link
Member

acerix commented Sep 3, 2020

It seems like this issue is specific to the React component that happens by updating the state in react which conflicts with the calendar automatically updating it's copy of the events.

But it should work by updating the event with "Technique 2", did you try code like this?

https://github.com/fullcalendar/fullcalendar-example-projects/blob/master/react-redux/src/DemoApp.jsx#L117

@acerix acerix transferred this issue from fullcalendar/fullcalendar Sep 3, 2020
@Phibedy
Copy link
Author

Phibedy commented Sep 4, 2020

Hi @acerix,

As far as I understand this and reducers: fullcalendar/fullcalendar-react#65 (comment)
There should not be a difference between using a reducer or not. In general a reducer is just an efficient/smart way of modifying a large object. I don't think it should change anything else.

Nevertheless, maybe I am missing something. As far as I understand the example:
https://github.com/fullcalendar/fullcalendar-example-projects/blob/master/react-redux/src/reducer.js#L27
Just sets the plainObject of an {id:event} object. If an event was modified, a new selector is given to the DemoApp.
https://github.com/fullcalendar/fullcalendar-example-projects/blob/master/react-redux/src/DemoApp.jsx#L165
It will always be a new array, but some event references will be the same.
Therefore there should be no difference if the event is in the state/props or using a reducer.

In my case using a reducer that way is not possible, because the events are calculated from a larger object which does not hold the events directly.

One thing I noticed about the example:
In https://github.com/fullcalendar/fullcalendar-example-projects/blob/master/react-redux/src/actions.js#L36 the state is updated using the object from the event.
This could fail at this point, as just the reference is copied.

if (ui.classNames.length) {

@Phibedy
Copy link
Author

Phibedy commented Oct 9, 2020

Are there any updates? Is this planned to be fixed? :)

@arshaw
Copy link
Member

arshaw commented Oct 14, 2020

when merging the new event into with the running events array, don't just merge in an EventApi object, use EventApi::toPlainObject instead...

https://codesandbox.io/s/quirky-nightingale-vr1k1?file=/src/DemoApp.jsx

https://fullcalendar.io/docs/Event-toPlainObject

@arshaw
Copy link
Member

arshaw commented Oct 14, 2020

I'm looking into some of the other problems now...

@arshaw
Copy link
Member

arshaw commented Oct 14, 2020

I'm unable to get the events to duplicate after switching to toPlainObject.

There's an artificial lag caused by the sleep, but that's expected.

Does toPlainObject solve your problem?

@Phibedy
Copy link
Author

Phibedy commented Oct 14, 2020

Thank you for the work-around, I will give it a try :)
The problem I am facing is, that I can not modify the event state from the calendar component as the calendar component just receives them as props. So for example if I modify one event, the backend modifies some other events automatically too. Therefore there is no chance I can use toPlainObject that easily.

I will try writting a wrapper around FullCalendar which merges the events hold by the calendar and the events passed from react using toPlainObject. But I have to say, that I do not like that approach, as this seems to be quite hacky :)

@Herz3h
Copy link

Herz3h commented Oct 27, 2020

Same issue on fullcalendar-vue 5.3.0

ezgif com-gif-maker

In my case, this code is used on every eventDrop:

        async onEventDrop(data)
        {
            var end = data.event.end;
            if(end == null)
            {
                end = dayjs(data.event.start).toDate();
            }

            this.changeDate(data.event, data.revert);
        },

        async changeDate(event, revert)
        {
            try
            {
                await $.post({
                    url: Routing.generate('calendar_changedate'),
                    data: {
                        id: event.id,
                        start: dayjs(event.start).format("YYYY-MM-DD HH:mm"),
                        end: dayjs(event.end).format("YYYY-MM-DD HH:mm"),
                        isAllDay: false
                    }
                });
            }
            catch(e)
            {
                revert()
            }
        },

Edit:

I also checked your react example @arshaw , and it still duplicates:

image

@Herz3h
Copy link

Herz3h commented Oct 28, 2020

In my case I found why it does this. Basically I move an event from day A to day B, then I drag from day B but do not drop yet, meanwhile my events are fetched from the server, here is an example, you can see the network tab (first request is change request, second is an all events fetch):

Oct-28-2020 07-28-09

An example: https://codesandbox.io/s/misty-monad-xb6jy?file=/src/DemoApp.jsx

@sebap100
Copy link

sebap100 commented Jan 27, 2021

when merging the new event into with the running events array, don't just merge in an EventApi object, use EventApi::toPlainObject instead...

https://codesandbox.io/s/quirky-nightingale-vr1k1?file=/src/DemoApp.jsx

https://fullcalendar.io/docs/Event-toPlainObject

@arshaw
I still have the issue with your solution (even in your codesandbox).
Please, try to drag and drop an event into a different time slot and immediately after dropping the event, re-drag it (within the 2 seconds) to another time slot without dropping it, you will see that the event is still duplicated.

This issue occurs exactly when you are dragging an event, at the same time that a React setState occurs in the background (in this case in the setTimeout callback). This causes a render of the component. Thus, the events given to FullCalendar through the events props are displayed again.

When the render occurs, it is like the moving event is unsync with the initial dragging event when a render occurs during the move. Thus, when dropping, FullCalendar creates a broad new event.

@Pyakz
Copy link

Pyakz commented Apr 26, 2022

duplicates.mp4

@saravanan-smartmd
Copy link

saravanan-smartmd commented Sep 2, 2022

Have there been any updates on this matter? Our team is reporting the same issue with latest release version. Thanks!

Our package json dependencies of FullCalendar:
"@fullcalendar/core": "^5.11.0",
"@fullcalendar/daygrid": "^5.11.0",
"@fullcalendar/interaction": "^5.11.0",
"@fullcalendar/react": "^5.11.1",
"@fullcalendar/rrule": "^5.11.3",
"@fullcalendar/timegrid": "^5.11.0",
"@fullcalendar/bootstrap5": "^5.11.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",

@FrancoRodao
Copy link

Have there been any updates on this matter? Our team is reporting the same issue with latest release version. Thanks!

Our package json dependencies of FullCalendar: "@fullcalendar/core": "^5.11.0", "@fullcalendar/daygrid": "^5.11.0", "@fullcalendar/interaction": "^5.11.0", "@fullcalendar/react": "^5.11.1", "@fullcalendar/rrule": "^5.11.3", "@fullcalendar/timegrid": "^5.11.0", "@fullcalendar/bootstrap5": "^5.11.0", "react": "^17.0.2", "react-dom": "^17.0.2",

One way I found to solve it is to edit the events only synchronously, I mean to have a local state of the events and manipulate them from there

@saravanan-smartmd
Copy link

saravanan-smartmd commented Sep 2, 2022

Have there been any updates on this matter? Our team is reporting the same issue with latest release version. Thanks!
Our package json dependencies of FullCalendar: "@fullcalendar/core": "^5.11.0", "@fullcalendar/daygrid": "^5.11.0", "@fullcalendar/interaction": "^5.11.0", "@fullcalendar/react": "^5.11.1", "@fullcalendar/rrule": "^5.11.3", "@fullcalendar/timegrid": "^5.11.0", "@fullcalendar/bootstrap5": "^5.11.0", "react": "^17.0.2", "react-dom": "^17.0.2",

One way I found to solve it is to edit the events only synchronously, I mean to have a local state of the events and manipulate them from there

Thank you, Franco! BTW, I have the synchronous approach working. However, the problem is when syncing the drag and drop event state changes to a call to the backend API call to update the modified data through a confirmation dialog when the user has dropped a recurring (both instance or series) or a non-recurring event. Our goal is to use build something akin to the demo shown here (https://clickermonkey.github.io/dayspan-vuetify/example/) but using FullCalendar.io and React. The wider community of FullCalendar React users will greatly benefit from such as example as most examples are too trivial to use for any real world implementation. Any pointers and suggestions are much appreciated. Thanks again!

@FrancoRodao
Copy link

FrancoRodao commented Sep 2, 2022

Have there been any updates on this matter? Our team is reporting the same issue with latest release version. Thanks!
Our package json dependencies of FullCalendar: "@fullcalendar/core": "^5.11.0", "@fullcalendar/daygrid": "^5.11.0", "@fullcalendar/interaction": "^5.11.0", "@fullcalendar/react": "^5.11.1", "@fullcalendar/rrule": "^5.11.3", "@fullcalendar/timegrid": "^5.11.0", "@fullcalendar/bootstrap5": "^5.11.0", "react": "^17.0.2", "react-dom": "^17.0.2",

One way I found to solve it is to edit the events only synchronously, I mean to have a local state of the events and manipulate them from there

Thank you, Franco! BTW, I have the synchronous approach working. However, the problem is when syncing the drag and drop event state changes to a call to the backend API call to update the modified data through a confirmation dialog when the user has dropped a recurring (both instance or series) or a non-recurring event. Our goal is to use build something akin to the demo shown here (https://clickermonkey.github.io/dayspan-vuetify/example/) but using FullCalendar.io and React. The wider community of FullCalendar React users will greatly benefit from such as example as most examples are too trivial to use for any real world implementation. Any pointers and suggestions are much appreciated. Thanks again!

I don't know if it helps, but a while ago I made a project with fullcalendar and the only way I found to solve this problem of synchronizing the data with the backend is to have two states, one local and one in the backend, the data that is already in backend should only be used in frontend initialization, then when I add/modify/remove events I make calls to the backend to update the state there, but when I update the state in the frontend I don't use the state returned by the backend, instead I use the local state parallel to that of the backend. It is difficult to explain it but I leave you the link of the repo so you can get a better idea https://github.com/FrancoRodao/MERN-Calendar I used redux to have the local state in frontend, but I think session/local storage would work fine too

@saravanan-smartmd
Copy link

Thank you, Franco! This was indeed an approach that our team tried, but the coordination to manage parallel states and the code required to manage these states (including handling exceptions that come from the server) made this a bit unwieldy for us to implement. Have a wonderful day!

I don't know if it helps, but a while ago I made a project with fullcalendar and the only way I found to solve this problem of synchronizing the data with the backend is to have two states, one local and one in the backend, the data that is already in backend should only be used in frontend initialization, then when I add/modify/remove events I make calls to the backend to update the state there, but when I update the state in the frontend I don't use the state returned by the backend, instead I use the local state parallel to that of the backend. It is difficult to explain it but I leave you the link of the repo so you can get a better idea https://github.com/FrancoRodao/MERN-Calendar I used redux to have the local state in frontend, but I think session/local storage would work fine too

@arshaw arshaw transferred this issue from fullcalendar/fullcalendar-react Dec 15, 2022
@arshaw arshaw added this to the upcoming-release milestone Jan 31, 2023
@arshaw
Copy link
Member

arshaw commented Feb 7, 2023

This problem has been fixed in v6.1.3

Updated repro and ported to stackblitz:
https://stackblitz.com/edit/github-yxh8xk?file=README.md

In order to prevent this bug, developers are responsible for the following:

  • Ensuring a unique id property on each event. This functions like React's key property. It correlates same items between rerenders.
  • If you are spreading and EventApi's properties in an object (for giving data to a redux store for example), use toPlainObject before spreading the props.

I plan to add this to official docs very soon.

@arshaw arshaw closed this as completed Feb 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants