HextaUI

useToday

A data de hoje, que se atualiza à meia-noite e quando a aba volta, sem divergência de hidratação.

"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

Adiciona o hook e tudo de que ele depende ao seu projeto.

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

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

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

Recorra a ele sempre que um componente depender da data atual, como destacar hoje, desabilitar dias passados ou fazer contagem regressiva até um prazo.

const today = new Date()

Ler a data durante a renderização quebra de duas formas:

  • Divergências de hidratação. O servidor renderiza no seu fuso horário, possivelmente horas antes. Perto da meia-noite, servidor e navegador discordam sobre o dia, e o React descarta o HTML do servidor.
  • Datas desatualizadas. Uma aba deixada aberta durante a noite continua mostrando ontem como hoje até que algo a renderize de novo.

useToday retorna undefined no servidor e durante a hidratação, e depois a data local. Também renderiza de novo à meia-noite e quando a aba volta a ficar visível, porque os temporizadores em abas em segundo plano podem ser pausados e perder a meia-noite.

Limites de data

Desabilite dias passados e qualquer coisa a mais de 30 dias. Até hoje ser conhecido, nada é desabilitado, para o HTML do servidor coincidir com a primeira renderização do cliente.

"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())

O arquivo também exporta as peças com que o hook é construído. As chaves de data são strings locais YYYY-MM-DD. Elas comparam por dia, ordenam corretamente e são seguras como keys do React ou chaves de cache. subscribeToday chama você de volta à meia-noite e na volta à aba, fora do React.

  • A Date retornada é a meia-noite no horário local, então compará-la com < ou > compara dias, não horários.
  • O mesmo objeto Date volta até o dia mudar, então é seguro usá-lo em dependências de effect.
  • Planeje a renderização com undefined. Um skeleton, ou renderizar sem limites baseados em data, ambos funcionam.
RetornaDescrição
Date | undefinedMeia-noite local de hoje. undefined no servidor e durante a hidratação.
ExportaçãoDescrição
toDateKey(date)Uma Date como string local YYYY-MM-DD.
fromDateKey(key)Uma string YYYY-MM-DD como uma Date na meia-noite local.
getTodayKey()A chave de data de hoje.
subscribeToday(callback)Chama de volta à meia-noite e quando a aba fica visível. Retorna uma função para cancelar a assinatura.

Calendar, e Date picker por meio dele.