React中如何基于旧值更新对象状态的date属性实现日期递增?
正确实现React中点击按钮递增日期的方法
原代码的问题
- 初始状态将
currDate存储为本地化日期字符串(new Date().toLocaleDateString()的返回值),字符串类型没有setDate、getDate这类Date对象的方法,点击按钮时会直接报错。 - 即使存储的是Date对象,直接修改原对象(如
date.currDate.setDate(...))会导致状态引用未发生变化,React无法感知到状态更新,可能不会触发组件重渲染,同时违反了React状态不可变的原则。
修正方案
- 初始状态存储Date实例:保留日期的原始对象类型,方便后续调用日期方法。
- 创建新的Date副本更新状态:每次递增日期时,基于当前日期创建新的Date实例,修改后再更新状态,保证状态的不可变性。
- 渲染时转换为本地化字符串:仅在需要显示的时候,将Date对象转为用户友好的本地化日期格式。
完整修正代码
const { useState } = React; const DateComponent = () => { // 初始状态存储Date对象,而非字符串 const [date, setDate] = useState({ currDate: new Date(), active: true }); const nextDate = () => { // 创建当前日期的副本,避免修改原状态对象 const newDate = new Date(date.currDate); // 递增一天 newDate.setDate(newDate.getDate() + 1); // 不可变更新状态,保留原有属性 setDate({ ...date, currDate: newDate }); }; return ( <div> {/* 渲染时转换为本地化日期字符串 */} <span>{date.currDate.toLocaleDateString()}</span> <button onClick={nextDate}>Next Day</button> </div> ); } ReactDOM.createRoot( document.getElementById("root") ).render( <DateComponent /> );
<div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
额外优化:使用函数式更新
如果组件存在频繁更新的场景,建议使用函数式更新获取最新状态,避免因状态快照导致的更新错误:
const nextDate = () => { setDate(prevDate => { const newDate = new Date(prevDate.currDate); newDate.setDate(newDate.getDate() + 1); return { ...prevDate, currDate: newDate }; }); };
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

