React中如何在视图层正确使用更新后的日期状态值?
React日期状态渲染错误解决方案
问题说明
开发React项目时,需实现两处日期展示:
- span元素:选中日期后替换“Select calendar”文本
- h2标签:显示选中日期
渲染时出现两个错误:
- 使用
{appointmentDate.toLocaleDateString()}时,报错Cannot read properties of undefined (reading 'toLocaleDateString') - 直接使用
{appointmentDate}时,报错Objects are not valid as a React child (found: [object Date])
原代码:
import { useRef, useState } from "react"; import { Calendar } from "react-date-range"; import { addDays } from "date-fns"; import { format } from "date-fns"; import "react-date-range/dist/styles.css"; // main css file import "react-date-range/dist/theme/default.css"; // theme css file export default function App() { const [appointmentDate, setAppointmentDate] = useState(new Date()); const handleDate = (e) => { const clickedDate = e.target.value; setAppointmentDate(clickedDate); document.getElementById("select-calendar").innerHTML = appointmentDate.toLocaleDateString(); console.log(appointmentDate); }; return ( <div className="App"> <span id="select-calendar">Select calendar</span> <div onClick={handleDate}> <Calendar onChange={(item) => setAppointmentDate(item)} date={appointmentDate} className="stay-date" name="appointmentDate" /> </div> <h2>{appointmentDate.toLocaleDateString()}</h2> </div> ); }
错误原因
- 状态更新异步+事件取值错误:
handleDate中尝试读取刚更新的appointmentDate(React状态更新是异步的,此时值未更新),且点击日历非输入元素时e.target.value为undefined,导致状态被设为undefined,后续调用toLocaleDateString报错。 - 直接渲染Date对象:React无法直接渲染Date类型对象,必须转为字符串。
- 手动操作DOM:使用
document.getElementById修改DOM不符合React状态驱动的设计理念,容易导致视图与状态不一致。
解决方案
修改后的代码如下:
import { useState } from "react"; import { Calendar } from "react-date-range"; import "react-date-range/dist/styles.css"; import "react-date-range/dist/theme/default.css"; export default function App() { const [appointmentDate, setAppointmentDate] = useState(new Date()); // 直接利用Calendar组件的onChange回调接收选中的日期 const handleDateChange = (selectedDate) => { setAppointmentDate(selectedDate); }; // 统一格式化日期为字符串 const formattedDate = appointmentDate.toLocaleDateString(); return ( <div className="App"> {/* 用状态控制span文本,无需手动操作DOM */} <span>{formattedDate}</span> <Calendar onChange={handleDateChange} date={appointmentDate} className="stay-date" /> <h2>{formattedDate}</h2> </div> ); }
关键修改点
- 移除外层
div的onClick事件,直接使用Calendar组件自带的onChange回调,该回调会直接返回选中的Date对象,避免了从事件对象取值的错误。 - 去掉手动操作DOM的代码,通过状态
formattedDate控制span的文本,让React自动同步视图与状态。 - 提前将Date对象格式化为字符串,确保渲染的是React支持的字符串类型,解决“Objects are not valid as a React child”错误。
- 状态更新后,React自动触发组件重渲染,两处视图会同步显示最新的格式化日期。
内容的提问来源于stack exchange,提问作者Kanishk Bisen
相关产品推荐
相关产品推荐

