React组件中date-fns格式化日期重渲染时未更新问题
React中date-fns日期格式化不随year props更新的问题
我在React组件中使用date-fns处理日期时遇到异常:组件接收数字类型的year作为props,通过date-fns的format方法生成日期字符串,但当year props变更后,格式化后的日期字符串却未随之更新。最初怀疑是useMemo导致的问题,但移除useMemo后问题依然存在。
代码示例
import { startOfYear, endOfYear, format } from "date-fns"; import { useMemo } from "react"; import { formatDateToYearMonthDay } from "./formatDateToYearMonthDay"; interface IProps { year?: number; } export function ForecastInfo({ year = new Date().getFullYear() }: IProps) { console.log("year", year); // const fromDateMemoDateFns = useMemo( // () => formatDateToYearMonthDay(startOfYear(year)), // [year] // ); // const toDateMemoDateFns = useMemo( // () => formatDateToYearMonthDay(endOfYear(year)), // [year] // ); // Why the hell stays the same? const fromDateMemoDateFns = format(startOfYear(year), "yyyy-MM-dd"); const toDateMemoDateFns = format(endOfYear(year), "yyyy-MM-dd"); const fromDateMemo = useMemo(() => `${year}-01-01`, [year]); const toDateMemo = useMemo(() => `${year}-12-31`, [year]); const fromDate = `${year}-01-01`; const toDate = `${year}-12-31`; const requestParams = { FromDate: fromDate, ToDate: toDate, }; console.log("requestParams", requestParams); return ( <div> <p>Year: {year}</p> <p>fromDate: {fromDate}</p> <p>toDate: {toDate}</p> <p>fromDateMemo: {fromDateMemo}</p> <p>toDateMemo: {toDateMemo}</p> <p>fromDateMemoDateFns: {fromDateMemoDateFns}</p> <p>toDateMemoDateFns: {toDateMemoDateFns}</p> </div> ); }
问题原因
date-fns的startOfYear和endOfYear方法要求传入Date对象,但你直接传递了数字类型的year。当数字传入这些方法时,date-fns会将其解析为时间戳(毫秒数),而非年份。比如传入2024,会被当作1970年1月1日加上2024毫秒,最终结果还是1970年的日期,所以无论year怎么变,格式化结果都不会更新。
解决方案
将数字类型的year转换为对应年份的Date对象后,再传给date-fns的方法:
方法1:使用new Date()创建Date对象
// 修复后的date-fns调用 const fromDateMemoDateFns = format(startOfYear(new Date(year, 0)), "yyyy-MM-dd"); const toDateMemoDateFns = format(endOfYear(new Date(year, 0)), "yyyy-MM-dd");
注:
new Date(year, 0)中第二个参数0代表1月(因为JavaScript的月份从0开始计数)
方法2:使用date-fns的parseISO方法
import { parseISO } from "date-fns"; const fromDateMemoDateFns = format(startOfYear(parseISO(`${year}-01-01`)), "yyyy-MM-dd"); const toDateMemoDateFns = format(endOfYear(parseISO(`${year}-01-01`)), "yyyy-MM-dd");
通过上述方式,当year props变更时,会生成对应年份的Date对象,date-fns就能正确格式化出更新后的日期字符串。
内容的提问来源于stack exchange,提问作者Hayk Safaryan
相关产品推荐
相关产品推荐

