如何阻止我的组件在开发中被制作两次
How to stop my component from being made twice in development
我正在关注这个 tutorial 以在 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
似乎是 运行ning 两次。如果我运行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>
)
希望对您有所帮助。
我正在关注这个 tutorial 以在 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
似乎是 运行ning 两次。如果我运行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>
)
希望对您有所帮助。