Hooks
useEventStream
Подписка на серверный поток событий с паузой в скрытой вкладке.
Подписка на серверный поток событий (SSE). Типичное применение — «живой» экран: сервер сообщает «что-то изменилось», а страница сама подтягивает свежие данные без перезагрузки и без потери прокрутки.
Пример
import { useEventStream } from "@toimetdev/pathlogs-hooks";
import { LiveIndicator } from "@toimetdev/pathlogs-core";
const { status, updatedAt } = useEventStream(`/api/projects/${id}/stream`, {
events: ["change"],
onEvent: () => router.refresh(),
});
<LiveIndicator status={status} updatedAt={updatedAt} locale="ru-RU" />Переподключение — не наша забота: EventSource делает это сам. Наше дело — честно показать, что связи сейчас нет.
Параметры
| Проп | Тип | По умолчанию | Описание |
|---|---|---|---|
url* | string | null | — | Адрес потока. null отключает подписку — удобно, пока id ещё не известен. |
onEvent | (event: MessageEvent) => void | — | Что делать при событии. Читается в момент события, стабильная ссылка не нужна. |
events | string[] | ["message"] | Имена событий SSE, на которые реагировать. |
deferWhenHidden | boolean | true | Откладывать обработку, пока вкладка скрыта, и выполнить один раз при возврате. |
enabled | boolean | true | Выключить подписку, не снимая хук. |
withCredentials | boolean | false | Передавать куки — нужно для авторизованных потоков на другом домене. |
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:
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" },
});
}