setter方法会在React中触发DOM重新渲染吗?

问题描述

我正在通过做一个基本的日历应用来学习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);