javascriptreact-nativewhile-loopdate-fnsreact-native-calendars

My react-native-app freezes when i use while loop


This component displays calendar to the patients so that they can select the appointment day from the appointment days of doctor. Doctor appointment days are fetched from api. What i am trying to achieve is to disable all other weekdays days in the calendar except the doctor appointment days so that patients can only press one of the appointment days. i am using react-native-calendars library and date-fns-library for dates. However my app is freezing once while loop is being defined. What am i doing wrong here ? Also is there a better way of doing what i am trying to achieve?

import { View } from "react-native";
import React, { useEffect, useState } from "react";
import { Calendar, CalendarProps } from "react-native-calendars";
import startOfMonth from "date-fns/startOfMonth";
import endOfMonth from "date-fns/endOfMonth";
import isBefore from "date-fns/isBefore";
import addDays from "date-fns/addDays";
import format from "date-fns/format";
import setDay from "date-fns/setDay";
import api from "../../config/api";
import Layout from "../UI/Layout";
import RegularText from "../UI/Text/RegularText";
import { useAppSelector } from "../../store/hooks";
import { useRoute } from "@react-navigation/native";
import { AppointmentDaysScreenRouteProp } from "../../@types/navigation";

const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] as const;

type weekday = typeof weekdays[number];

const CalendarComponent = () => {
  const language = useAppSelector((state) => state.language.selected);
  const [markedDates, setMarkedDates] = useState<CalendarProps["markedDates"]>(
    {}
  );
  const [disabledledWeekdays, setDisbaledWeekdays] = useState<number[]>([]);
  const route = useRoute<AppointmentDaysScreenRouteProp>();

  const { doctorId } = route.params;

  const [loading, setLoading] = useState(true);

  let text = {
    loading: "...Please wait",
  };

  if (language === "اردو") {
    text = {
      loading: "...لوڈ ہو رہا ہے",
    };
  }

  useEffect(() => {
    (async () => {
      try {
        const res = await api.get<{ appointmentDays: weekday[] }>(
          `/appointments/appointmentDays/doctorId/${doctorId}`
        );

        const { appointmentDays } = res.data;
        const disabledDays = weekdays
          .filter((item) => !appointmentDays.includes(item))
          .map((item) => weekdays.indexOf(item));

        const now = new Date();

        getDisabledDays(now.getMonth(), now.getFullYear(), disabledDays);

        setDisbaledWeekdays(disabledDays);
      } finally {
        setLoading(false);
      }
    })();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const getDisabledDays = (
    month: number,
    year: number,
    daysIndexes: number[]
  ) => {
    const now = new Date();

    now.setFullYear(year, month);

    const pivot = startOfMonth(now);
    const end = endOfMonth(now);
    const dates: CalendarProps["markedDates"] = {};

    const disabled = { disabled: true, disableTouchEvent: true };
    //THIS WHILE LOOP IS FREEZING MY APP
    //IF I REMOVE THIS LOOP APP WORKS FINE
    while (isBefore(pivot, end)) {
      daysIndexes.forEach((day) => {
        const copy = setDay(new Date(pivot), day);
        dates[format(copy, "yyyy-MM-dd")] = disabled;
      });
      addDays(pivot, 7);
    }
    setMarkedDates(dates);
    return dates;
  };

  return (
    <Layout>
      <View>
        {loading ? (
          <RegularText>{text.loading}</RegularText>
        ) : (
          <Calendar
            theme={{
              textSectionTitleDisabledColor: "#d9e1e8",
            }}
            markedDates={markedDates}
            onDayPress={(day) => {
              console.log("dosomething with ", day);
            }}
            firstDay={1}
            enableSwipeMonths={true}
            disabledDaysIndexes={disabledledWeekdays}
             onMonthChange={(date) => {
               getDisabledDays(date.month - 1, date.year, disabledledWeekdays);
             }}
          />
        )}
      </View>
    </Layout>
  );
};

export default CalendarComponent;

Solution

  • Looking at the documentation, I'm it seems that addDays(date, amount) is returning a new date and not modifying the value of pivot. Try doing pivot = addDays(pivot, 7)