Multi Month Plugin Forced reflow while executing JavaScript causing laggy interactions
Reduced Test Case
https://codesandbox.io/s/quizzical-chandrasekhar-8kux86?file=/src/App.js
Do you understand that if a reduced test case is not provided, we will intentionally delay triaging of your ticket?
- [X] I understand
Which connector are you using (React/Angular/etc)?
React
Bug Description
Hello,
I'm using full-calendar 6.1.4 for the react connector.
When im using multiMonthPlugin with interactionPlugin and dayGridPlugin i get a warning on my console saying : "[Violation] 'click' handler took 220ms" "[Violation] Forced reflow while executing JavaScript took <N>ms"
It happens everytime i load the page, change dates etc
Thanks.
This also happens with on some demo pages (e.g. event interaction) so I assume it is a general problem. Seems to be the same as #6741
@DevDotJoel and @septatrix , I believe you when you say this his happening, but unfortunately I'm not able to recreate. Does this happen upon page load, or after you do some action?
Could you record everything (including dev console where this error is appearing) with a screen capture tool like https://gifcap.dev/ ?
@acerix, a recreation from you would be great as well!
As can be seen in the screencast it is not completely deterministic and probably depends on CPU utilization etc.
Making a performance recording seems to reveal that this is due to calling getBoundingClientRect() in the PositionCache which always results in a style recalculation, i.e. forced reflow, given that any of the DOM changed compared to the last time this was called:
https://github.com/fullcalendar/fullcalendar/blob/8660e4d7327e68d15c2253d02c56a66fa1a7420e/packages/core/src/common/PositionCache.ts#L20
As it seems like this cache exists precisely to reduce this impact there does not seems to be a simple fix for this. Improving DOM structure, CSS selectors/styles etc could improve this though that is likely a rather cumbersome process. However, I noticed that the only DOM change (at least in my case) is the addition and removal of the fc-unselectable class to the body element. I am not sure which purpose it fulfills though running document.body.classList.add = console.log and thus preventing the classlist from changing prevented the violations to show up. I am sure there is a reason to set this class but just wanted to share my investigation so far and confirm my suspicion about the reflow cause.
Finally, I am not sure whether @DevDotJoel is experiencing this in the same scenario or under slightly different circumstances as they also mention page loads and date changes. In those two cases I only rarely get the warning (though the calendar I am testing with is rather empty currently), and I fear that in those cases it will be a lot harder to change anything about it (as basically the whole DOM changes in those scenarios).
In v6.1.5 I've eliminated the fc-selectable className. The problem of reflow while clicking most likely won't be a problem anymore. Could @septatrix and @DevDotJoel please verify? If it helps, I've updated fullcalendar.io's demos page and docs examples to use the latest version
While .fc-selectable no longer gets applied it seems that you simply set the CSS style directly which seems to still seems to invalidate the layout and leads to a forced reflow upon the subsequent getBoundingClientRect invocation. I am not sure why this is the case, maybe someone more knowledgeable in the CSS spec or the corresponding browser engines might explain what is going on here.
May I ask why the class/style gets applied and removed upon click/release? It seems like this is only the case for calendars with selectable or editable (at least by checking the different demo calendars). Would it be possible to simply apply the user-select: none style to the whole calendar upon initialization if one of those plugins is active and explicitly remove it on events which have editing disabled? This way it would not have to be set and removed all the time. Maybe someone could explain the purpose of why this is required.
Also I would like to emphasize that for me this is barely noticeable and hundreds of ms as reported by Joel. I mostly see values around 50ms. I mostly participate as it bugs me to see warnings in the dev console and problems like these can often point to underlying issues.
While
.fc-selectableno longer gets applied it seems that you simply set the CSS style directly which seems to still seems to invalidate the layout and leads to a forced reflow upon the subsequentgetBoundingClientRectinvocation. I am not sure why this is the case, maybe someone more knowledgeable in the CSS spec or the corresponding browser engines might explain what is going on here.May I ask why the class/style gets applied and removed upon click/release? It seems like this is only the case for calendars with
selectableoreditable(at least by checking the different demo calendars). Would it be possible to simply apply theuser-select: nonestyle to the whole calendar upon initialization if one of those plugins is active and explicitly remove it on events which have editing disabled? This way it would not have to be set and removed all the time. Maybe someone could explain the purpose of why this is required.Also I would like to emphasize that for me this is barely noticeable and hundreds of ms as reported by Joel. I mostly see values around 50ms. I mostly participate as it bugs me to see warnings in the dev console and problems like these can often point to underlying issues.
Hey, im still facing the same issue but the ms is lower. In my case im using a modal that when u choose a date it opens with input fields using states. Everytime i delete the input it lags and it shows the reflow message
this problem is still ocurring in these versions: "@fullcalendar/core": "^6.1.10", "@fullcalendar/multimonth": "^6.1.10", "@fullcalendar/react": "^6.1.10",
I also noticed this happens if i only use multiMonthPlugin
is there a fix for this anytime soon?
this problem is still ocurring in these versions: "@fullcalendar/core": "^6.1.10", "@fullcalendar/multimonth": "^6.1.10", "@fullcalendar/react": "^6.1.10",
I also noticed this happens if i only use multiMonthPlugin
is there a fix for this anytime soon?
i even opened the example that you guys give here : https://fullcalendar.io/docs/multimonth-stack-demo
When i open the console i saw the same warning : Forced reflow while executing JavaScript took 90ms. Just refresh the page over and over and you will see.
I've found this no longer happens in the newly-released v7.0.0-beta.0. Performance for multimonth view is much better.
Updated repro: https://codepen.io/arshaw/pen/OJKMOQZ?editors=001