[英]How to stop my component from being made twice in development
我正在按照本教程在 React 中制作一個 javascript 日歷
我有一個包含以下代碼的工作日歷 UI
// https://medium.com/@nitinpatel_20236/challenge-of-building-a-calendar-with-pure-javascript-a86f1303267d
import { useState, useEffect, 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 = useMemo(() => new Date(), []);
const [currentMonth, setCurrentMonth] = useState(today.getMonth())
const [currentYear, setCurrentYear] = useState(today.getFullYear())
const calendarBodyRef = useRef<HTMLDivElement>(null)
// 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()
}
useEffect(() => {
const showCalendar = (month: number, year: number) => {
const firstDay = (new Date(year, month)).getDay()
const calendarBody = calendarBodyRef.current
// creating all cells
let date = 1;
for (let i = 0; i < 6; i++) {
// creates a table row
const row = document.createElement("div")
row.classList.add(styles.row)
//creating individual cells, filing them up with data.
for (let j = 0; j < 7; j++) {
if (i === 0 && j < firstDay) {
const cell = document.createElement("div")
cell.classList.add(styles.cell)
const cellText = document.createTextNode("")
cell.appendChild(cellText)
row.appendChild(cell)
} else if (date > daysInMonth(month, year)) {
break
} else {
const cell = document.createElement("div")
cell.classList.add(styles.cell)
const cellText = document.createTextNode(String(date))
if (date === today.getDate() && year === today.getFullYear() && month === today.getMonth()) {
cell.classList.add(styles.currentDay)
} // color today's date
cell.appendChild(cellText)
row.appendChild(cell)
date++
}
}
if (calendarBody) {
calendarBody.appendChild(row) // appending each row into calendar body.
}
}
}
showCalendar(currentMonth, currentYear)
}, [currentMonth, currentYear, today])
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}>
</div>
</div>
</>
)
}
export default Home
但是在開發中,我的日歷制作了兩次
我假設這是因為React.StrictMode
在開發中,因為useEffect
似乎運行了兩次。 如果我運行npm run build
和npm start
模擬生產,我只會看到一個日歷。
我的日歷是否還有辦法在開發中出現一次?
您遇到的問題是 useEffect 中的依賴項在新的渲染周期中發生變化,因此 showCalendar 被多次觸發。
為了保留您的代碼並且只運行一次,您應該能夠定義變量:
const today = ...
const currentMonth = ...
const currentYear = ...
並從 useEffect 中刪除依賴項,因為它們不會改變:
showCalendar(currentMonth, currentYear)
}, [])
但是 useEffect 是完全沒有必要的,而且你的方法很奇怪。
做就是了:
<div ref={calendarBodyRef} className={styles.calendarBody}>
{months.map(month => {
return <div>[...your logic here]<div>
})}
</div>
或者:
const getMonthElement = (month) => {
return <div>[your month logic]<div>
}
...
return(
<div ref={calendarBodyRef} className={styles.calendarBody}>
{months.map(month => {
return <div>[...your logic here]<div>
})}
</div>
)
希望有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.