Skip to main content

Troubleshooting

The following are the most common issues found when using Flash Calendar and a guide on how to fix them.

FlashList's rendered size is not usable.

Check out Flash List docs for instructions on how to fix this warning.

TLDR: ensure the parent of <Calendar.List /> has a fixed height or a flex: 1 style.

ReferenceError: Can't find variable: Intl (Android)

Flash Calendar uses Intl primitives to format dates in a locale-aware way. JavaScriptCore (jsc), the legacy React Native JS runtime, doesn't support Intl out of the box on Android.

It's highly advised to upgrade to Hermes, the new default JS runtime (more on that). Besides better performance, it also supports the Intl primitives Flash Calendar uses. For Expo, update your app.json to use hermes:

{
"expo": {
"jsEngine": "hermes"
}
}

If your company is stuck with jsc, you can either use a polyfill, or bypass Intl entirely by providing your own date formatting functions.

Calendar.List is slow when using date ranges

If you're seeing frame drops when using Calendar.List, there's a high chance you're suffering from too many re-renders. If you're not careful with memoization, the entire list re-renders whenever the calendarActiveDateRanges prop changes. Notice the frame drops and how each BaseCalendar re-renders in the React DevTools profiler (this is bad 👎):

import { Calendar, toDateId } from "@marceloterreiro/flash-calendar";
import { addMonths } from "date-fns";
import { Text } from "react-native";

const todayId = toDateId(new Date());
const maxDateId = toDateId(addMonths(new Date(), 12));

export const SlowExample = () => {
const [dateIds, setDateIds] = useState<string[]>([]);
const dateRanges = dateIds.map((dateId) => ({
startId: dateId,
endId: dateId,
}));

return (
<Calendar.VStack alignItems="stretch" grow spacing={12}>
<Text>⚠️ Don't copy-paste this example, it has performance issues</Text>

<Calendar.List
calendarActiveDateRanges={dateRanges}
calendarInitialMonthId={todayId}
calendarMaxDateId={maxDateId}
calendarMinDateId={todayId}
onCalendarDayPress={(dateId) => {
if (dateIds.includes(dateId)) {
setDateIds(dateIds.filter((id) => id !== dateId));
} else {
setDateIds([...dateIds, dateId]);
}
}}
/>
</Calendar.VStack>
);
};

The easiest fix is to use the provided useDateRange hook. The hook is optimized by default and works perfectly with Calendar.List.

However, there might be cases where you need to control the onCalendarDayPress event and decide how the date range logic works. In those cases, make sure you memoize the onCalendarDayPress and use the updater function pattern. Notice it runs on 60 FPS and the BaseCalendar components don't re-render anymore (this is good 👍):

import type { CalendarOnDayPress } from "@marceloterreiro/flash-calendar";
import { Calendar, toDateId } from "@marceloterreiro/flash-calendar";
import { addMonths } from "date-fns";
import { useCallback, useState } from "react";
import { Text } from "react-native";

const todayId = toDateId(new Date());
const maxDateId = toDateId(addMonths(new Date(), 12));

export const SlowExampleAddressed = () => {
const [dateIds, setDateIds] = useState<string[]>([]);
const dateRanges = dateIds.map((dateId) => ({
startId: dateId,
endId: dateId,
}));

// This is the fix: memoized onCalendarDayPress and updater function pattern
// It keeps `BaseCalendar` props stable, allowing each month to skip re-renders
const handleCalendarDayPress = useCallback<CalendarOnDayPress>((dateId) => {
setDateIds((dateIds) => {
if (dateIds.includes(dateId)) {
return dateIds.filter((id) => id !== dateId);
} else {
return [...dateIds, dateId];
}
});
}, []);

return (
<Calendar.VStack alignItems="stretch" grow spacing={12}>
<Text>✅ This is safe to copy, perf issues addressed</Text>

<Calendar.List
calendarActiveDateRanges={dateRanges}
calendarInitialMonthId={todayId}
calendarMaxDateId={maxDateId}
calendarMinDateId={todayId}
onCalendarDayPress={handleCalendarDayPress}
/>
</Calendar.VStack>
);
};