You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 17:35:12