dayComponent too many renders
First of all, thank you for creating the react-native calendar. However, there is an issue with the customization of the DayComponent that causes too much rendering
This is due to the function or object comparison that goes into the props of the Calendar component.
It stems from the 'areEqual' function in react-native-calendars/src/calendar/day/index.js:11 not working correctly.
The specific point of misbehavior is In the above-mentioned index.js file, on line 14, the omit function of lodash is incorrectly executed. This is because functions like onPress, onLongPress, or objects specified by theme have different references when compared in the _.some function, so the React.memo function thinks it's a different object every time it's executed, and it doesn't work correctly. So every time you click on a date within the same month, you'll see all 30+ components performing unnecessary operations that render over and over again.
Therefore, we need to add logic to ignore the comparison when comparing functions or objects.
//before
function areEqual(prevProps, nextProps) {
const prevPropsWithoutMarkDates = omit(prevProps, 'marking');
const nextPropsWithoutMarkDates = omit(nextProps, 'marking');
const didPropsChange = some(prevPropsWithoutMarkDates, function (value, key) {
return value !== nextPropsWithoutMarkDates[key];
});
const isMarkingEqual = isEqual(prevProps.marking, nextProps.marking);
return !didPropsChange && isMarkingEqual;
}
// after
function areEqual(prevProps, nextProps) {
const prevPropsWithoutMarkDates = omit(prevProps, 'marking');
const nextPropsWithoutMarkDates = omit(nextProps, 'marking');
const didPropsChange = some(prevPropsWithoutMarkDates, function (value, key) {
if (typeof nextPropsWithoutMarkDates[key] === 'function') {
return false;
}
if (typeof nextPropsWithoutMarkDates[key] === 'object') {
return false;
}
return value !== nextPropsWithoutMarkDates[key];
});
const isMarkingEqual = isEqual(prevProps.marking, nextProps.marking);
return !didPropsChange && isMarkingEqual;
}
and after all, I used library code as below
}) => {
const today = useRef(dayjs().format('YYYY-MM-DD'));
const [selectedDate, setSelectedDate] = useState(today.current);
const [testID, setTestID] = useState(0);
const onMonthChange = (date: DateData) => {
onMonthPress(date);
setTestID(date.month);
};
useEffect(() => {
setTestID(Date.now());
}, [customParentArrayObject]);
return (
<Calendar
testID={testID.toString()}
onDayPress={({ dateString }) => {
onDatePress(dateString);
setSelectedDate(dateString);
}}
markedDates={{
[today.current]: { today: true },
[selectedDate]: { selected: true, },
}}
renderHeader={renderHeader}
theme={{
arrowColor: '#222222',
arrowStyle: { paddingHorizontal: 53 },
textSectionTitleColor: '#b6c1cd',
selectedDayBackgroundColor: '#00adf5',
todayTextColor: 'blue',
dayTextColor: 'red',
}}
onMonthChange={onMonthChange}
dayComponent={(props) => <CustomDayComponent customArrayObject={customParentArrayObject} props={props} />}
hideExtraDays={true}
disableAllTouchEventsForDisabledDays={true}
disableAllTouchEventsForInactiveDays={true}
/>
);
};
Does anyone know if there is a pull request for this issue?
is there any solution for this issue