HextaUI

useToday

Das heutige Datum, das um Mitternacht und bei der Rückkehr zum Tab weiterläuft, ohne Hydration-Mismatch.

"use client"

import { Skeleton } from "@/components/ui/skeleton"
import { useToday } from "@/hooks/use-today"

const formatter = new Intl.DateTimeFormat(undefined, { dateStyle: "full" })

function daysUntilNewYear(today: Date) {
  const next = new Date(today.getFullYear() + 1, 0, 1)
  return Math.round((next.getTime() - today.getTime()) / 86_400_000)
}

export function UseTodayDemo() {
  const today = useToday()

  return (
    <div className="flex flex-col items-center gap-1 text-center">
      {today ? (
        <>
          <p className="text-lg font-medium">{formatter.format(today)}</p>
          <p className="text-sm text-muted-foreground">
            {daysUntilNewYear(today)} days until New Year
          </p>
        </>
      ) : (
        <>
          <Skeleton className="h-6 w-56" />
          <Skeleton className="mt-1 h-4 w-36" />
        </>
      )}
    </div>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/use-today.json

Fügt den Hook und alles, wovon er abhängt, zu deinem Projekt hinzu.

import { useToday } from "@/hooks/use-today"
const today = useToday()

if (!today) {
  return <Skeleton className="h-5 w-40" />
}

return <p>{format(today, "PPPP")}</p>

Greife danach, sobald eine Komponente vom aktuellen Datum abhängt, etwa um heute hervorzuheben, vergangene Tage zu deaktivieren oder bis zu einer Frist herunterzuzählen.

const today = new Date()

Das Lesen des Datums beim Rendern geht auf zwei Arten schief:

  • Hydration-Mismatches. Der Server rendert in seiner Zeitzone, möglicherweise Stunden früher. Nahe Mitternacht sind sich Server und Browser über den Tag uneinig, und React verwirft das Server-HTML.
  • Veraltete Daten. Ein über Nacht offener Tab zeigt gestern weiter als heute an, bis etwas anderes ihn neu rendert.

useToday gibt auf dem Server und während der Hydration undefined zurück, danach das lokale Datum. Es rendert auch um Mitternacht und wenn der Tab wieder sichtbar wird neu, da Timer in Hintergrund-Tabs pausiert werden und Mitternacht verpassen können.

Datumsgrenzen

Deaktiviere vergangene Tage und alles, was mehr als 30 Tage in der Zukunft liegt. Solange heute nicht bekannt ist, ist nichts deaktiviert, sodass das Server-HTML zum ersten Client-Render passt.

"use client"

import { addDays } from "date-fns"

import { Calendar } from "@/components/ui/calendar"
import { useToday } from "@/hooks/use-today"

export function UseTodayBounds() {
  const today = useToday()

  return (
    <Calendar
      mode="single"
      disabled={today ? [{ before: today }, { after: addDays(today, 30) }] : []}
    />
  )
}
import {
  fromDateKey,
  getTodayKey,
  subscribeToday,
  toDateKey,
} from "@/hooks/use-today"

toDateKey(new Date(2026, 9, 5))
fromDateKey("2026-10-05")

const unsubscribe = subscribeToday(() => refreshAgenda())

Die Datei exportiert auch die Bausteine, aus denen der Hook gebaut ist. Date-Keys sind lokale YYYY-MM-DD-Strings. Sie vergleichen sich nach Tag, sortieren korrekt und sind sicher als React-Keys oder Cache-Keys. subscribeToday ruft dich um Mitternacht und bei Rückkehr zum Tab zurück, außerhalb von React.

  • Das zurückgegebene Date ist Mitternacht in lokaler Zeit, sodass ein Vergleich mit < oder > Tage vergleicht, nicht Uhrzeiten.
  • Dasselbe Date-Objekt kommt zurück, bis sich der Tag ändert, und ist daher sicher in Effect-Abhängigkeiten.
  • Plane den undefined-Render ein. Ein Skeleton oder Rendern ohne datumsbasierte Grenzen funktionieren beide.
RückgabeBeschreibung
Date | undefinedLokale Mitternacht heute. undefined auf dem Server und während der Hydration.
ExportBeschreibung
toDateKey(date)Ein Date als lokaler YYYY-MM-DD-String.
fromDateKey(key)Ein YYYY-MM-DD-String als Date um lokale Mitternacht.
getTodayKey()Der Date-Key von heute.
subscribeToday(callback)Ruft um Mitternacht und wenn der Tab wieder sichtbar wird zurück. Gibt eine Unsubscribe-Funktion zurück.

Calendar und darüber Date picker.