使用localStorage后出现RangeError: Invalid Time Value问题求助
问题
开发论坛时,通过表单收集用户输入,将话题标题、内容、作者和日期以对象形式存入topic数组,映射渲染到页面展示所有话题的创建者和日期。为了页面刷新后保留数据,引入localStorage存储数组,核心代码如下:
const [topic, setTopic] = useState(() => { const topicJson = localStorage.getItem("topic"); return topicJson ? JSON.parse(topicJson) : []; }); const updatedTopic = [ ...topic, { title: title, message, author: "Dagger", date: new Date(), }, ]; setTopic(updatedTopic);
使用date-fns的format方法将日期格式化为M/dd h:mma样式时,未用localStorage前正常,引入后抛出错误:
throw new RangeError('Invalid time value'); // Convert the date in system timezone to the same date in UTC+00:00 timezone. // This ensures that when UTC functions will be implemented, locales will be compatible with them.
直接显示date则正常,需要解决该错误。
解决方案
问题根源是localStorage只能存储JSON格式数据,Date对象被序列化后会变成字符串,从localStorage取出解析时,date字段不再是Date对象,导致date-fns的format方法无法识别。
方法一:初始化时统一还原Date对象
在useState初始化函数里,将解析后的数组中每个date字符串转回Date对象,后续操作直接用标准Date对象:
const [topic, setTopic] = useState(() => { const topicJson = localStorage.getItem("topic"); if (!topicJson) return []; // 遍历数组,把date字符串还原为Date对象 return JSON.parse(topicJson).map(item => ({ ...item, date: new Date(item.date) })); });
同时要确保每次更新topic后同步到localStorage(建议用useEffect监听):
useEffect(() => { localStorage.setItem("topic", JSON.stringify(topic)); }, [topic]);
之后渲染和排序逻辑无需修改,直接使用format(date, "M/dd h:mma")即可。
方法二:渲染/排序时临时转换
如果不想修改数组存储结构,可在渲染和排序时临时将date字符串转为Date对象:
{topic .sort((a, b) => new Date(b.date) - new Date(a.date)) // 排序时转换为Date对象 .map(({ date }, index) => ( <tr key={index}> <td>{format(new Date(date), "M/dd h:mma")}</td> // 渲染时转换 </tr> ))}
注意:排序必须同步转换,否则字符串类型的日期排序会出现逻辑错误。
内容的提问来源于stack exchange,提问作者Dagger
相关产品推荐
相关产品推荐

