PathLogs UI
English

Hooks

useEventStream

Подписка на серверный поток событий с паузой в скрытой вкладке.

Подписка на серверный поток событий (SSE). Типичное применение — «живой» экран: сервер сообщает «что-то изменилось», а страница сама подтягивает свежие данные без перезагрузки и без потери прокрутки.

Пример

обновлено в 09:05

Переподключение — не наша забота: EventSource делает это сам. Наше дело — честно показать, что связи сейчас нет.

Параметры

url*string | null

Адрес потока. null отключает подписку — удобно, пока id ещё не известен.

onEvent(event: MessageEvent) => void

Что делать при событии. Читается в момент события, стабильная ссылка не нужна.

eventsstring[]

по умолчанию: ["message"]

Имена событий SSE, на которые реагировать.

deferWhenHiddenboolean

по умолчанию: true

Откладывать обработку, пока вкладка скрыта, и выполнить один раз при возврате.

enabledboolean

по умолчанию: true

Выключить подписку, не снимая хук.

withCredentialsboolean

по умолчанию: false

Передавать куки — нужно для авторизованных потоков на другом домене.

Возвращает { status, updatedAt }, где статус — connecting, live или offline.

Скрытая вкладка

Хранится только последнее событие: экран всё равно перечитывает состояние целиком, и накапливать очередь незачем.

Сторона сервера

Хук ничего не предполагает о сервере, кроме формата SSE. Минимальный обработчик в Next.js:

app/api/projects/[id]/stream/route.ts
export async function GET(req: Request, { params }) {
  const encoder = new TextEncoder();
  let version = await projectVersion(params.id);

  const stream = new ReadableStream({
    async start(controller) {
      const send = (event: string, data: string) =>
        controller.enqueue(encoder.encode(`event: ${event}\ndata: ${data}\n\n`));

      send("sync", version);

      const timer = setInterval(async () => {
        const next = await projectVersion(params.id);
        if (next !== version) {
          version = next;
          send("change", next);
        }
      }, 4000);

      // Соединение закрываем сами, не дожидаясь лимита платформы:
      // браузер переподключится, и поток не оборвётся по таймауту хостинга
      setTimeout(() => {
        clearInterval(timer);
        controller.close();
      }, 45_000);
    },
  });

  return new Response(stream, {
    headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-store" },
  });
}