<Calendar
testID={`${testID}-calendar`}
current={currentMonth}
minDate={minDateString}
maxDate={maxDateString}
onDayPress={onDayPress}
dayComponent={renderDay}
theme={calendarTheme}
renderArrow={renderArrow}
enableSwipeMonths={false}
disableMonthChange={false}
hideArrows={false}
disableArrowLeft={shouldDisableLeftArrow}
disableArrowRight={shouldDisableRightArrow}
hideExtraDays={false}
onMonthChange={(month: DateData) => {
setCurrentMonth(month.dateString);
}}
style={styles.calendar}
/>
/**
* Custom day component renderer
* Displays day number, lunar calendar info, and peak day indicators
* Optimized with memoized DayComponent to prevent unnecessary re-renders
* @param day - Day data from calendar
*/
const renderDay = useCallback(
(day: { date?: DateData; state?: string }) => {
if (!day.date) return null;
const dateString = day.date.dateString;
const isSelected = dateString === selectedDate;
// Use pre-calculated today date string for faster comparison
const isToday = dateString === todayDateString;
// Check if date is disabled (before min or after max)
// Use pre-calculated date strings for faster comparisons
const isDisabled: boolean =
day.state === 'disabled' ||
dateString < minDateString ||
Boolean(maxDateString && dateString > maxDateString);
// Calculate isCanNotChoose only if minimumDate exists
let isCanNotChoose = false;
if (minimumDate) {
const dateWithTime = DateTimeHelpers.toDateTz({
timezone,
date: dateString,
})
.hour(valueHour)
.minute(valueMinute);
const todayStart = DateTimeHelpers.toDateTz().startOf('day');
const minDateMinusOne = DateTimeHelpers.toDateTz({
timezone,
date: minimumDate,
}).subtract(1, 'minute');
isCanNotChoose = Boolean(
DateTimeHelpers.checkIsBetween({
timezone,
date: dateWithTime,
startDate: todayStart,
endDate: minDateMinusOne,
}),
);
}
// Check if it's a peak day (weekend or holiday)
// Cache day of week calculation
const dayOfWeek = DateTimeHelpers.getDayOfWeek({
timezone,
date: dateString,
});
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
// Only check holiday if not already a weekend (short-circuit optimization)
const isHoliday =
!isWeekend && Boolean(checkHoliday(dateString, timezone));
const isPeakDay: boolean = isWeekend || isHoliday;
// Get lunar calendar info
const lunarInfo = getLunaHoliday(dateString, timezone);
return (
<DayComponent
day={day.date}
isSelected={isSelected}
isToday={isToday}
isDisabled={isDisabled}
isCanNotChoose={isCanNotChoose}
isPeakDay={isPeakDay}
lunarInfo={lunarInfo}
onDayPress={onDayPress}
/>
);
},
[
selectedDate,
todayDateString,
minDateString,
maxDateString,
timezone,
minimumDate,
valueHour,
valueMinute,
onDayPress,
],
);
Calendar is very slow when selecting day on Android
Description
The
Calendarcomponent experiences significant performance issues when selecting a day on Android devices. There's a noticeable delay (2000-5000ms+) when tapping a day, making the calendar feel unresponsive.Steps to Reproduce
CalendarExpected Behavior
Actual Behavior
Environment
Technical Details
Component uses
react-native-calendarswith customDayComponentandrenderDaycallback. Despite existing optimizations (React.memo, useMemo, useCallback), Android still experiences lag duringonDayPressexecution.Possible Causes
onDayPressImpact
My source