wix / react-native-calendars

React Native Calendar Components 🗓️ 📆
MIT License
9.58k stars 2.96k forks source link

The period of the selection type is rendered very slowly in the CalendarList #2262

Open Mokutte opened 1 year ago

Mokutte commented 1 year ago

Description

The period of the selection type is rendered very slowly in the CalendarList

Expected Behavior

I wanted to use the period selection in the CalendarList, but after clicking the button becomes active after 1-2 seconds. But if you use a regular Calendar, then everything works quickly. This happens regardless of the version of the device and regardless of whether it is iOS or Android

Environment

"react-native": "0.72.0" "react-native-calendars": "^1.1299.0"

Also specify:

  1. Device/emulator/simulator & OS version:

Reproducible Demo


import dayjs from 'dayjs';
import React, {useMemo, useState} from 'react';
import {SafeAreaView, StatusBar, useColorScheme} from 'react-native';
import {Calendar, CalendarList, DateData} from 'react-native-calendars';

import {MarkedDates, Theme} from 'react-native-calendars/src/types';

function App(): JSX.Element {
  const isDarkMode = useColorScheme() === 'dark';

  const theme: Theme = {
    backgroundColor: '#fff',
    calendarBackground: '#fff',
    selectedDayBackgroundColor: '#4fc030',
    todayTextColor: '#4fc030',
    dayTextColor: '#000',
    textDisabledColor: '#8d8d8d',
    monthTextColor: '#000',
  };

  const [startValue, setStartValue] = useState<any>();
  const [finishValue, setFinishValue] = useState<any>();
  const [periodValue, setPeriodValue] = useState();

  const getDateFromTimestamp = (value: number) =>
    dayjs(value).format('YYYY-MM-DD');

    const getPeriod = (startTimestamp: number, endTimestamp: number) => {
      const period: MarkedDates = {}

      let currentTimestamp = startTimestamp

      while (currentTimestamp < endTimestamp) {
        const dateString = getDateFromTimestamp(currentTimestamp)
        const startingDay = currentTimestamp === startTimestamp

        period[dateString] = {
          color: startingDay ? '#4fc030' : '#4fc03073',
          startingDay,
          customContainerStyle:  { borderRadius: 4 }
        }

        currentTimestamp += 24 * 60 * 60 * 1000
      }

      period[getDateFromTimestamp(endTimestamp)] = {
        color: '#4fc030',
        endingDay: true,
        customContainerStyle:  { borderRadius: 4 }
      }

      return period
    }

    const period = useMemo(() => {
      if (startValue !== undefined && finishValue === undefined) {
        const dateString = getDateFromTimestamp(startValue)
        return {
          [dateString]: {
            color: '#4fc030',
            endingDay: true,
            startingDay: true,
            customContainerStyle: { borderRadius: 4 }
          }
        }
      } else if (finishValue !== undefined && startValue !== undefined) {
        const periodValue = getPeriod(startValue, finishValue)

        return periodValue
      }
    }, [startValue, finishValue])

  const onDayPress = (dayObj: DateData) => {
    const {day, month, year} = dayObj;

    const timestamp = new Date(year, month - 1, day).getTime();

    console.log('дата нажатия', timestamp);

    if (
      startValue === undefined ||
      (startValue !== undefined && finishValue !== undefined)
    ) {
      setStartValue(timestamp);
      setFinishValue(undefined);
    } else {
      if (startValue > timestamp) {
        setStartValue(timestamp);
        setFinishValue(startValue);
      } else {
        setFinishValue(timestamp);
      }
    }
  };

  console.log(startValue, finishValue);

  return (
    <SafeAreaView>
      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
      <CalendarList
        minDate={dayjs().format('YYYY-MM-DD')}
        markingType={'period'}
        markedDates={period}
        futureScrollRange={5}
        onDayPress={onDayPress}
        theme={theme}
      />
    </SafeAreaView>
  );
}

export default App;
stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

jeremykanso commented 4 months ago

This is still a huge issue. Not usable in production imo.

I investigated and can say that this issue exist since 1.1280.0.

I tried to identify what in 1.128.0 was causing the issue but didn't find what exactly