React中TimeAgo组件报Invalid time value错误求助
React TimeAgo组件报错Uncaught RangeError: Invalid time value 排查解决
问题背景
在React项目中使用TimeAgo组件实现时间展示功能,向模拟API提交日期时持续触发Uncaught RangeError: Invalid time value错误,错误发生在formatDistanceToNow方法调用环节,组件接收post.date作为timestamp属性。
相关代码
TimeAgo组件代码
import { parseISO, formatDistanceToNow } from 'date-fns'; import React from 'react' export default function TimeAgo({timestamp}) { let timeAgo = '' if (timestamp) { const date = parseISO(timestamp) const timePeriod = formatDistanceToNow(date) timeAgo = `${timePeriod} ago` } return ( <span title={timestamp}> <i>{timeAgo}</i> </span> ) }
组件调用代码
import TimeAgo from './TimeAgo' import ReactionButton from './ReactionButton' export default function PostsExcerpt({post}) { return ( <article> <h2>{post.title}</h2> <p>{post.body.substring(0, 100)}</p> <p> <PostAuthor userId={post.userId} /> <TimeAgo timestamp={post.date} /> </p> <ReactionButton post={post}/> </article> ) }
报错栈信息
index.js:110 Uncaught RangeError: Invalid time value at formatDistance (index.js:110:1) at formatDistanceToNow (index.js:92:1) at TimeAgo (TimeAgo.js:8:1) at renderWithHooks (react-dom.development.js:16305:1) at mountIndeterminateComponent (react-dom.development.js:20074:1) at beginWork (react-dom.development.js:21587:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1) at beginWork$1 (react-dom.development.js:27451:1) The above error occurred in the <TimeAgo> component: at TimeAgo (http://localhost:3000/static/js/bundle.js:697:5) at p at article at PostsExcerpt (http://localhost:3000/static/js/bundle.js:488:5) at section at Post (http://localhost:3000/static/js/bundle.js:107:76) at App at Provider (http://localhost:3000/static/js/bundle.js:38579:5) Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
问题分析
报错核心是formatDistanceToNow接收到了无效的日期对象,根源在于:
post.date不符合parseISO要求的ISO 8601标准格式(比如是"2024-05-20 12:00"这类非标准格式,或是Unix时间戳数字);- 外层
if(timestamp)仅判断了值是否存在,但没校验格式有效性,导致parseISO返回无效Date对象,进而触发formatDistanceToNow报错。
解决方案
方案1:兼容多格式日期+有效性校验
修改TimeAgo组件,增加对Unix时间戳的兼容,同时校验解析后的日期是否有效:
import { parseISO, formatDistanceToNow, isValid } from 'date-fns'; import React from 'react' export default function TimeAgo({timestamp}) { let timeAgo = '' if (timestamp) { let date; // 兼容Unix时间戳(数字或字符串形式的数字) if (!isNaN(Number(timestamp))) { date = new Date(Number(timestamp)); } else { // 尝试解析ISO格式字符串 date = parseISO(timestamp); } // 校验日期有效性,有效才格式化 if (isValid(date)) { const timePeriod = formatDistanceToNow(date); timeAgo = `${timePeriod} ago`; } else { timeAgo = '无效日期'; } } return ( <span title={timestamp}> <i>{timeAgo}</i> </span> ) }
方案2:修复API返回的日期格式
检查模拟API返回的post.date字段,确保其为标准ISO 8601格式(例如"2024-05-20T12:34:56.000Z"),从数据源层面解决格式问题。
方案3:增加异常捕获
通过try-catch包裹日期格式化逻辑,避免单个无效日期导致组件崩溃:
import { parseISO, formatDistanceToNow } from 'date-fns'; import React from 'react' export default function TimeAgo({timestamp}) { let timeAgo = '' if (timestamp) { try { const date = parseISO(timestamp); const timePeriod = formatDistanceToNow(date); timeAgo = `${timePeriod} ago`; } catch (err) { console.error('日期格式化失败:', err); timeAgo = '无效日期'; } } return ( <span title={timestamp}> <i>{timeAgo}</i> </span> ) }
调试建议
- 在TimeAgo组件中添加
console.log('当前timestamp:', timestamp),确认post.date的实际内容,定位格式问题; - 使用
isValid函数单独校验解析后的日期对象,判断是解析环节还是数据源格式的问题。
内容的提问来源于stack exchange,提问作者Aderoba Dayo Jerry
相关产品推荐
相关产品推荐

