React StrictMode: day-grid events remain permanently invisible (visibility: hidden) in v7.0.1
Bug description
In v7.0.1 (@fullcalendar/react), day-grid events can end up permanently invisible: the event elements are present in the DOM but carry inline visibility: hidden, and nothing (refetching, prev/next navigation, view switches, window resizes) ever makes them visible again. Only a full remount of the calendar recovers.
We found two triggers with the same end state:
- React
<StrictMode>(dev) — events are invisible immediately on mount, 100% reproducible with the minimal snippet below. Note the v7 release notes state StrictMode is now supported. - Re-render while a Bootstrap (reactstrap) modal opens over the calendar — observed in our application in a production build (no StrictMode double-invoking): opening any modal above the calendar leaves all events
visibility: hiddenafter the modal closes. We could not yet isolate this second trigger into a standalone snippet, but the resulting DOM state is identical to the StrictMode case, so it appears to be the same underlying measurement issue.
What the stuck state looks like
The event harness element (rendered by renderFgSegs in the daygrid code) keeps inline visibility: hidden and its absolutely-positioning parent has height 0:
div (event title text) → computed visibility: hidden
div.fc-… (event harness, pos:absolute) → inline style visibility: hidden, top not set
div (abs container) → 135x0 (height 0)
div (day row) → normal size, visibleReading the v7 source, renderFgSegs sets visibility: hidden while top == null, and top comes from segTops, which is derived from height measurements collected through segHeightRefMap / ResizeObserver callbacks. In the broken state that measurement pass apparently never completes, so top stays null forever and the events remain hidden.
Minimal reproduction (StrictMode trigger)
@fullcalendar/react 7.0.1, react / react-dom 19.2.8, temporal-polyfill 1.0.1. Chromium (also reproduced in Chrome headless).
import React, { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/react/daygrid';
import '@fullcalendar/react/skeleton.css';
import '@fullcalendar/react/themes/classic/theme.css';
import '@fullcalendar/react/themes/classic/palette.css';
createRoot(document.getElementById('root')).render(
<StrictMode>
<FullCalendar
plugins={[dayGridPlugin]}
initialView="dayGridMonth"
initialDate="2026-07-22"
events={[
{ title: 'event one', start: '2026-07-10T10:00:00' },
{ title: 'event two', start: '2026-07-15T10:00:00' }
]}
/>
</StrictMode>
);Expected: both events visible on the July 2026 month grid.
Actual: the calendar chrome renders fine, but the events are in the DOM with visibility: hidden and never appear. Remove <StrictMode> and they render correctly.
The same snippet with height={650} and an async eventSources function behaves identically, so it is not related to sizing mode or event source type.
Second trigger (production, no StrictMode)
In our app (React 19 + reactstrap), with a production React build:
- Month view with events renders fine.
- Open any Bootstrap modal above the calendar (this re-renders the calendar's parent and applies Bootstrap's body scroll lock).
- Close the modal.
- All events are now
visibility: hidden(same DOM state as above). No event-source request is made;refetchEvents(), prev/next month, and view switches do not recover; a page refresh (fresh mount) does.
A simple imitation (fixed overlay + body { overflow: hidden; padding-right: 15px }) did not reproduce it standalone, so reactstrap/Bootstrap appears to interact with the measurement pipeline in some additional way we haven't pinned down. Happy to help narrow this down further.
Workaround we use
Remounting the calendar (changing its React key) after every modal close restores correct rendering, at the cost of a refetch.
Source: fullcalendar/fullcalendar