Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dayComponent too many renders #2451

Open
babpulss opened this issue Apr 17, 2024 · 1 comment
Open

dayComponent too many renders #2451

babpulss opened this issue Apr 17, 2024 · 1 comment

Comments

@babpulss
Copy link

babpulss commented Apr 17, 2024

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;
}
@babpulss
Copy link
Author

babpulss commented Apr 17, 2024

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}
    />
  );
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant