I'm trying to create a calendar page in my React project. When I am running the project, the only thing that is displayed is a small calendar populated only with the days and the 2 arrows which are doing nothing when pressed. In order to make it work, I comment the first renderCalendar(), and I decomment the second one. I receive a warning in my terminal : "Unreachable code". After that, I comment the 2nd renderCalendar() and decomment the first one and IT WORKS. But when I refresh the page, the simple calendar with only the days of the weeks is displayed again. Do you know how or where to call the function renderCalendar() in order to work from the first run?
import React from 'react';
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
export const Calendar = () => {
const currentDate = document.querySelector(".current-date") || {};
let daysTag = document.querySelector(".days") || {};
let prevNextIcon = document.querySelectorAll(".arrow");
// getting new date, current year and month
let date = new Date();
let currYear = date.getFullYear();
let currMonth = date.getMonth();
const months = ["January", "February", "March", "April",
"May", "June","July", "August", "September",
"October", "November", "December"];
const renderCalendar = () => {
//get last date of month
let firstDayofMonth = new Date(currYear, currMonth, 1).getDay();
let lastDateofMonth = new Date(currYear, currMonth + 1, 0).getDate();
let lastDayofMonth = new Date(currYear, currMonth, lastDateofMonth).getDay();
let lastDateofLastMonth = new Date(currYear, currMonth, 0).getDate();
let liTag= "";
for (let i = firstDayofMonth; i > 0; i--) {
liTag += `<li class= "inactive">${lastDateofLastMonth - i + 1}</li>`;
};
for(let i = 1; i<= lastDateofMonth; i++) {
let isToday = i === date.getDate() && currMonth === new Date().getMonth()
&& currYear === new Date().getFullYear() ? "active" : "";
liTag += `<li class="${isToday}">${i}</li>`;
};
for(let i = lastDayofMonth; i<= 5; i++) {
liTag += `<li class= "inactive">${i - lastDayofMonth + 1}</li>`;
};
// month and year
currentDate.innerText = `${months[currMonth]} ${currYear}`;
daysTag.innerHTML = liTag;
};
renderCalendar(); //<------------------------------------------------------------1st
prevNextIcon.forEach ( icon => {
icon.addEventListener("click", () => {
currMonth = icon.id === "prev" ? currMonth - 1 : currMonth + 1;
if(currMonth < 0 || currMonth > 11) {
date = new Date(currYear, currMonth);
currYear = date.getFullYear();
currMonth = date.getMonth();
}
else {
date = new Date();
};
renderCalendar();
});
});
return (
<div className="auth flexContainer">
<h1>Calendar</h1>
<div className="wrapper">
<header>
<p className="current-date">May</p>
<div className="icons">
<ArrowBackIosIcon id="prev" className="arrow"/>
<ArrowForwardIosIcon id="next" className="arrow"/>
</div>
</header>
<div className="calendar">
<ul className="weeks">
<li>Sunday</li>
<li>Monday</li>
<li>Tuesday</li>
<li>Wednesday</li>
<li>Thursday</li>
<li>Friday</li>
<li>Saturday</li>
</ul>
<ul className="days"></ul>
</div>
</div>
</div>
);
//renderCalendar(); // <-----------------------------------------------------------2nd
}
Do you know how or where to call the function renderCalendar() in order to work from the first run?
I must say that could be better ways to render the calendar, and design this component, this seems overcomplicated and I think there is no need to use querySelectors in this case, in react you can use refs instead. Having said this, you could set a flag state like,
const [renderedCalendar,setRenderedCalendar]=useState(false)
Then call your renderCalendar inside a useEffect like:
useEffect(()=>{
renderCalendar()
[renderCalendar]
Then inside your renderCalendar,at the end add setRenderedCalendar(true)
Make then a conditional render in the return:
{renderedCalendar&& <div className="auth flexContainer">....etc}
I recommend you to wrap this renderCalendar function into a useCallback.