问题描述
我正在通过做一个基本的日历应用来学习React,这主要依赖于使用Date()对象。我正在尝试显示所选的月份,方法是单击几个很棒的字体箭头图标来更改。
我使用上下文API和useState,通过“ setDateObject”回调更新日期,该回调使用Date对象的setter函数“ setMonth()”。
仅执行一些控制台日志即可显示状态已成功更新,但是
标记中显示的日期未重新显示。我尝试用硬类型对象切换日期对象,并在“ incrementMonth”方法中手动增加月份,这确实会触发重新渲染。
所以我误会了一些东西,或者使用setter函数更新日期对象只是没有触发重新渲染。有人有经验吗?
谢谢!
对象
import React,{ useContext } from "react"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
// Styling
import style from "../styles/Calendar.css"
// Assets
import { faArrowLeft } from "@fortawesome/free-solid-svg-icons"
import { faArrowRight } from "@fortawesome/free-solid-svg-icons"
// Contexts
import { DateContext } from "./context/DateContext.js"
const Calendar = () => {
const [dateObj,setDateObj] = useContext(DateContext)
const monthArray = ["January","February","march","April","May","June","July","August","September","October","November","December"];
const incrementMonth = () => {
setDateObj(prevDate => {
let newDate = prevDate
newDate.setMonth(prevDate.getMonth() + 1)
return newDate
})
}
const decrementMonth = () => {
setDateObj(prevDate => {
let newDate = prevDate
newDate.setMonth(prevDate.getMonth() - 1)
return newDate
})
}
return(
<div style={style} className="CalendarWrapper">
<div className="MonthSelector">
<FontAwesomeIcon icon={faArrowLeft} onClick={decrementMonth} className="hoverArrow"/>
<p>{ `${ monthArray[dateObj.getMonth()] } ${ dateObj.getFullYear() }` }</p>
<FontAwesomeIcon icon={faArrowRight} onClick={incrementMonth} className="hoverArrow"/>
</div>
</div>
)
}
export default Calendar
上下文
import React,{ useState,createContext } from "react"
export const DateContext = createContext(null)
export const DateProvider = props => {
const [dateObj,setDateObj] = useState(new Date())
return(
<DateContext.Provider value={[dateObj,setDateObj]}>
{props.children}
</DateContext.Provider>
)
}
解决方法
React尝试对重新渲染保持精明。如果新状态和旧状态是对相同值的引用,则it doesn't re-render。
实际上,您已经在使用相同的日期对象调用setDateObj
,即使您已更改其内部数据。换句话说,如果newDate === prevDate
,它将不会重新渲染。您可以通过这样复制日期来避免这种情况:
const newDate = new Date(prevDate);