Использование в React

Библиотека date-fns используется в React как набор чистых функций для работы с датами без состояния и скрытых зависимостей. Такой подход делает её предсказуемой в компонентах, облегчает тестирование и снижает риск побочных эффектов при ререндере.

Основной принцип интеграции — импортировать только нужные функции, избегая полного подключения библиотеки.

import { format, addDays, isAfter, parseISO } from "date-fns";

Каждая функция является независимой, что позволяет Tree Shaking и уменьшает итоговый бандл.


Форматирование дат в React-компонентах

Одной из самых частых задач является отображение даты в UI. В React форматирование обычно выполняется прямо в render-логике или через вычисляемые значения.

import { format } from "date-fns";

function PostDate({ createdAt }) {
  return (
    <time>
      {format(new Date(createdAt), "dd.MM.yyyy")}
    </time>
  );
}

Функция format не хранит состояния и не зависит от окружения, поэтому её безопасно вызывать при каждом рендере.


Оптимизация через useMemo

При частых рендерах форматирование даты может выполняться многократно. Для оптимизации используется useMemo, особенно если вычисления сложнее простого форматирования.

import { useMemo } from "react";
import { format } from "date-fns";

function EventCard({ event }) {
  const formattedDate = useMemo(() => {
    return format(new Date(event.startDate), "EEEE, d MMMM yyyy");
  }, [event.startDate]);

  return <div>{formattedDate}</div>;
}

useMemo предотвращает повторное вычисление при неизменном startDate, снижая нагрузку на рендеринг.


Работа с относительными датами

В интерфейсах часто требуется отображение разницы во времени: «2 дня назад», «через 3 часа». В date-fns для этого используется formatDistanceToNow.

import { formatDistanceToNow } from "date-fns";

function CommentTime({ date }) {
  return (
    <span>
      {formatDistanceToNow(new Date(date), { addSuffix: true })}
    </span>
  );
}

Эта функция автоматически вычисляет разницу относительно текущего времени, что делает её удобной для лент и комментариев.


Парсинг и работа с ISO-строками

В React-приложениях даты часто приходят с API в ISO-формате. Для безопасного преобразования используется parseISO.

import { parseISO, format } from "date-fns";

function Booking({ data }) {
  const date = parseISO(data.start_time);

  return <div>{format(date, "dd MMM yyyy HH:mm")}</div>;
}

Использование new Date() допустимо, но parseISO обеспечивает более предсказуемое поведение при строгих строковых форматах.


Сравнение дат в UI-логике

React-компоненты часто зависят от состояния даты: активность, доступность, истечение срока.

import { isAfter } from "date-fns";

function Promo({ expiresAt }) {
  const isExpired = isAfter(new Date(), new Date(expiresAt));

  return (
    <button disabled={isExpired}>
      Купить
    </button>
  );
}

Функции сравнения из date-fns позволяют избегать ручных вычислений через timestamp и делают код более декларативным.


Манипуляция датами: сдвиги и интервалы

Часто требуется вычислять будущие или прошлые даты: дедлайны, напоминания, расписания.

import { addDays, subHours } from "date-fns";

const deadline = addDays(new Date(), 7);
const reminder = subHours(deadline, 2);

В React такие вычисления обычно используются при подготовке данных перед рендером или внутри хуков.


Локализация дат

date-fns поддерживает локализацию через отдельные модули локалей. Это важно для интерфейсов с несколькими языками.

import { format } from "date-fns";
import { ru } from "date-fns/locale";

function LocalizedDate({ date }) {
  return (
    <div>
      {format(new Date(date), "d MMMM yyyy", { locale: ru })}
    </div>
  );
}

Локаль передаётся явно, что исключает глобальные зависимости и упрощает контроль над выводом.


Использование в React hooks

В сложных интерфейсах логика работы с датами выносится в кастомные хуки.

import { useMemo } from "react";
import { format, isBefore } from "date-fns";

function useEventStatus(eventDate) {
  return useMemo(() => {
    const date = new Date(eventDate);

    return {
      formatted: format(date, "dd.MM.yyyy"),
      isPast: isBefore(date, new Date())
    };
  }, [eventDate]);
}

Такой подход отделяет бизнес-логику от UI-компонентов.


SSR и Next.js

В серверном рендеринге (например, Next.js) важно учитывать различие часовых поясов между сервером и клиентом. date-fns работает детерминированно, но результат форматирования может зависеть от окружения.

import { format } from "date-fns";

export async function getServerSideProps() {
  const now = new Date();

  return {
    props: {
      time: format(now, "yyyy-MM-dd HH:mm:ss")
    }
  };
}

Чтобы избежать расхождений между сервером и клиентом, форматирование часто фиксируется на уровне сервера, а клиент получает уже готовую строку.


Изоляция логики дат от UI

В React-проектах распространена практика отделения работы с датами от компонентов. date-fns используется в утилитарных модулях.

// utils/date.js
import { format, isToday } from "date-fns";

export function formatMessageDate(date) {
  const d = new Date(date);

  if (isToday(d)) {
    return format(d, "HH:mm");
  }

  return format(d, "dd.MM.yyyy");
}
import { formatMessageDate } from "./utils/date";

function Message({ message }) {
  return <span>{formatMessageDate(message.createdAt)}</span>;
}

Такой подход снижает связность компонентов и упрощает повторное использование логики.


Работа с массивами дат в списках

React часто отображает списки событий, где каждую дату необходимо обработать.

import { format } from "date-fns";

function Timeline({ events }) {
  return (
    <ul>
      {events.map((event) => (
        <li key={event.id}>
          {format(new Date(event.date), "dd.MM.yyyy")} — {event.title}
        </li>
      ))}
    </ul>
  );
}

При больших списках стоит учитывать стоимость преобразований и выносить вычисления за пределы render при возможности.


Стабильность вычислений и повторные рендеры

React может вызывать рендеры часто, особенно при изменении состояния родительских компонентов. date-fns-функции не кэшируют результаты, поэтому повторные вызовы всегда выполняют вычисления заново.

Для стабилизации используются:

  • useMemo для вычислений внутри компонентов
  • подготовка данных на уровне селекторов (Redux, Zustand)
  • предварительная нормализация API-ответов

Работа с интервалами времени

Для построения UI таймеров и дедлайнов используется комбинация функций date-fns и React state.

import { useEffect, useState } from "react";
import { differenceInSeconds } from "date-fns";

function Countdown({ targetDate }) {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const target = new Date(targetDate);

    const id = setInterval(() => {
      setSeconds(differenceInSeconds(target, new Date()));
    }, 1000);

    return () => clearInterval(id);
  }, [targetDate]);

  return <div>{seconds}</div>;
}

Такой подход позволяет строить реактивные интерфейсы без сторонних библиотек состояния времени.


Особенности интеграции в масштабируемых проектах

При росте приложения date-fns обычно становится центральным инструментом работы с датами во всех слоях:

  • UI (React-компоненты)
  • бизнес-логика (сервисы)
  • слой API (нормализация данных)
  • утилиты форматирования

Ключевое преимущество — отсутствие глобального состояния и минимальная связность между модулями, что позволяет безопасно использовать функции в любом контексте React-архитектуры.