Работа с датами в интерфейсах React почти всегда связана с форматированием, пересчётом значений при изменении состояния и оптимизацией повторных вычислений. Day.js выступает компактной альтернативой Moment.js, сохраняя цепочный API и расширяемость через плагины, при этом легко встраивается в модель функциональных компонентов.
Основной принцип интеграции заключается в том, что Day.js не хранит состояние и не привязан к жизненному циклу компонентов. Он используется как чистая функция преобразования данных.
import dayjs from "dayjs";
function DateView({ timestamp }) {
const formatted = dayjs(timestamp).format("YYYY-MM-DD HH:mm");
return <div>{formatted}</div>;
}
Каждый рендер пересчитывает форматирование. Для простых случаев это допустимо, но при частых обновлениях может потребоваться оптимизация через мемоизацию.
При повторных рендерах одинаковых входных данных целесообразно избегать лишних вычислений.
import { useMemo } from "react";
import dayjs from "dayjs";
function DateView({ timestamp }) {
const formatted = useMemo(() => {
return dayjs(timestamp).format("DD.MM.YYYY");
}, [timestamp]);
return <span>{formatted}</span>;
}
useMemo здесь не изменяет поведение Day.js, но снижает количество вызовов форматирования при неизменном timestamp.
Частая задача — отображение «живого» времени, которое обновляется каждую секунду.
import { useEffect, useState } from "react";
import dayjs from "dayjs";
function Clock() {
const [now, setNow] = useState(dayjs());
useEffect(() => {
const id = setInterval(() => {
setNow(dayjs());
}, 1000);
return () => clearInterval(id);
}, []);
return <div>{now.format("HH:mm:ss")}</div>;
}
Ключевой момент заключается в том, что состояние хранит не строку, а объект Day.js, что упрощает дальнейшие преобразования без повторного парсинга.
Day.js часто используется для расчёта разницы между датами в зависимости от состояния компонента.
import { useMemo, useState } from "react";
import dayjs from "dayjs";
function Countdown({ target }) {
const [tick, setTick] = useState(0);
const diff = useMemo(() => {
return dayjs(target).diff(dayjs(), "second");
}, [target, tick]);
return <div>{diff}</div>;
}
Обновление tick может инициироваться таймером, создавая реактивный пересчёт разницы.
Повторяющаяся логика форматирования и обновления времени выносится в кастомный хук.
import { useEffect, useState } from "react";
import dayjs from "dayjs";
function useNow(interval = 1000) {
const [now, setNow] = useState(dayjs());
useEffect(() => {
const id = setInterval(() => {
setNow(dayjs());
}, interval);
return () => clearInterval(id);
}, [interval]);
return now;
}
Использование:
function Clock() {
const now = useNow(1000);
return <div>{now.format("HH:mm:ss")}</div>;
}
Такая абстракция упрощает повторное использование и отделяет временную логику от UI.
Day.js расширяется через плагины, что особенно важно при создании интерфейсов с относительным временем.
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
dayjs.extend(relativeTime);
Использование внутри React:
import { useEffect, useState } from "react";
import dayjs from "dayjs";
function RelativeTime({ date }) {
const [tick, setTick] = useState(0);
useEffect(() => {
const id = setInterval(() => setTick(t => t + 1), 60000);
return () => clearInterval(id);
}, []);
return <div>{dayjs(date).fromNow()}</div>;
}
Обновление раз в минуту достаточно для корректного отображения относительного времени без избыточных ререндеров.
При необходимости отображения локального времени разных регионов используется плагин timezone.
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
dayjs.extend(utc);
dayjs.extend(timezone);
Пример использования в компоненте:
function CityTime({ zone }) {
const now = dayjs().tz(zone);
return <div>{now.format("HH:mm")}</div>;
}
При изменении зоны компонент автоматически пересчитывает отображаемое значение без дополнительной логики.
Частая ошибка заключается в создании новых объектов Day.js на каждом рендере без необходимости. Это особенно заметно при списках.
function List({ items }) {
return items.map(item => {
const date = dayjs(item.createdAt).format("DD.MM.YYYY");
return <div key={item.id}>{date}</div>;
});
}
Если данные стабильны, форматирование можно заранее вычислять на уровне получения данных или через мемоизированный селектор.
Day.js часто используется для работы с датами в формах, где требуется синхронизация строкового ввода и внутреннего представления.
import { useState } from "react";
import dayjs from "dayjs";
function DateInput() {
const [value, setValue] = useState("");
const parsed = dayjs(value, "YYYY-MM-DD", true);
return (
<input
value={value}
onCha nge={(e) => setValue(e.target.value)}
/>
);
}
Строгий режим парсинга предотвращает некорректные преобразования и упрощает валидацию.
При использовании серверного рендеринга важно учитывать, что Day.js вычисляет дату в момент выполнения. Несовпадение времени между сервером и клиентом может привести к расхождениям.
const formatted = dayjs().format("HH:mm");
Для стабилизации результата применяется фиксация времени на сервере и передача его через props, чтобы клиент не пересчитывал значение при гидратации.
Сложные интерфейсы часто объединяют несколько временных источников: текущее время, относительное время и форматированные даты.
function useTimeModel(targetDate) {
const now = useNow(1000);
const formatted = useMemo(() => {
return dayjs(targetDate).format("DD MMMM YYYY");
}, [targetDate]);
const relative = useMemo(() => {
return dayjs(targetDate).from(now);
}, [targetDate, now]);
return { now, formatted, relative };
}
Такой подход разделяет вычисляемые значения и минимизирует дублирование логики внутри компонентов.
В некоторых случаях вместо интервалов используется внешнее событие обновления, например синхронизация с WebSocket или глобальным таймером приложения.
import { useEffect, useState } from "react";
import dayjs from "dayjs";
function useExternalClock(clockEvent) {
const [now, setNow] = useState(dayjs());
useEffect(() => {
const handler = (t) => setNow(dayjs(t));
clockEvent.subscribe(handler);
return () => clockEvent.unsubscribe(handler);
}, [clockEvent]);
return now;
}
Такой подход снижает нагрузку на UI и синхронизирует время между компонентами.
Day.js в React-архитектуре обычно используется по трём направлениям:
Изоляция этих зон через useMemo и кастомные хуки снижает связанность компонентов и упрощает масштабирование временной логики в приложении.