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