How do I stop resetting my date
variable back to 1
at the end of every row?
CodePudding user response:
Easy answer, extract your print into another function and call it with your component's return statement. Also note that your print statement is O(n^2) so re-rendering with be a costly operation.
Code:
import { useState, useRef, useMemo } from 'react'
import type { NextPage } from 'next'
import Head from 'next/head'
import styles from '../styles/Home.module.scss'
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
// console.log('render')
const Home: NextPage = () => {
const today = new Date()
const [currentMonth, setCurrentMonth] = useState(today.getMonth())
const [currentYear, setCurrentYear] = useState(today.getFullYear())
const calendarBodyRef = useRef<HTMLDivElement>(null)
const rows = 6
const cells = 7
const firstDay = (new Date(currentYear, currentMonth)).getDay()
// check how many days in a month code from https://dzone.com/articles/determining-number-days-month
const daysInMonth = (iMonth: number, iYear: number) => {
return 32 - new Date(iYear, iMonth, 32).getDate()
}
const renderCalendar = () => {
let date = 1;
return [...Array(rows).keys()].map((row) => {
return (
<div key={row} className={styles.row}>
{[...Array(cells).keys()].map((cell) => {
if (row === 0 && cell < firstDay) {
return (
<div key={cell} className={styles.cell}></div>
)
} else if (date > daysInMonth(currentMonth, currentYear)) {
return
} else {
const cellText = String(date)
date
return (
<div key={cell} className={styles.cell}>{cellText}</div>
)
}
})}
</div>
)
})}
}
return (
<>
<Head>
<title>Calendar Budget App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className={styles.calendarWrap}>
<h2 className={styles.monthTitle}>{months[currentMonth]} {currentYear}</h2>
<div className={styles.daysWrap}>
<span>Sun</span>
<span>Mon</span>
<span>Tue</span>
<span>Wed</span>
<span>Thu</span>
<span>Fri</span>
<span>Sat</span>
</div>
<div ref={calendarBodyRef} className={styles.calendarBody}>
{renderCalendar()}
</div>
</div>
</>
)
}
export default Home
CodePudding user response:
I like michmich112's answer but unfortunatly I can't comment on it (lack of reputation)
But you can improve the render time by adding useMemo
import { useState, useRef, useMemo } from 'react'
import type { NextPage } from 'next'
import Head from 'next/head'
import styles from '../styles/Home.module.scss'
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
// console.log('render')
const Home: NextPage = () => {
const today = new Date()
const [currentMonth, setCurrentMonth] = useState(today.getMonth())
const [currentYear, setCurrentYear] = useState(today.getFullYear())
const calendarBodyRef = useRef<HTMLDivElement>(null)
const rows = 6
const cells = 7
const firstDay = (new Date(currentYear, currentMonth)).getDay()
// check how many days in a month code from https://dzone.com/articles/determining-number-days-month
const daysInMonth = (iMonth: number, iYear: number) => {
return 32 - new Date(iYear, iMonth, 32).getDate()
}
const renderCalendar = useMemo(() => {
let date = 1;
return [...Array(rows).keys()].map((row) => {
return (
<div key={row} className={styles.row}>
{[...Array(cells).keys()].map((cell) => {
if (row === 0 && cell < firstDay) {
return (
<div key={cell} className={styles.cell}></div>
)
} else if (date > daysInMonth(currentMonth, currentYear)) {
return
} else {
const cellText = String(date)
date
return (
<div key={cell} className={styles.cell}>{cellText}</div>
)
}
})}
</div>
)
})}
}, [currentMonth, currentYear])
return (
<>
<Head>
<title>Calendar Budget App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className={styles.calendarWrap}>
<h2 className={styles.monthTitle}>{months[currentMonth]} {currentYear}</h2>
<div className={styles.daysWrap}>
<span>Sun</span>
<span>Mon</span>
<span>Tue</span>
<span>Wed</span>
<span>Thu</span>
<span>Fri</span>
<span>Sat</span>
</div>
<div ref={calendarBodyRef} className={styles.calendarBody}>
{renderCalendar()}
</div>
</div>
</>
)
}
export default Home