Загрузка данных на сервере
Дожидаемся результата и различаем HTTP-запрос, сборку и кэш.
On this page
Для Next.js 16.3.8 (App Router) и React 19.3.0. Обновлено .
В предыдущей статье серверная страница передавала массив в клиентский фильтр. Получение данных может занять время: например, при чтении файла, запросе к API или базе данных. Знакомые async и await позволяют описать это ожидание в серверном компоненте.
Начнем без внешнего сервиса
Сохраните lib/events.ts и app/events/event-filter.tsx из предыдущих статей. Создайте загрузчик с учебной задержкой:
import { events, type EventItem } from "./events";
export async function loadEvents(): Promise<EventItem[]> {
await new Promise<void>((resolve) => setTimeout(resolve, 700));
return events;
}Это имитация ожидания, а не запрос в интернет. Так можно изучить загрузку, не подключаясь к чужому сервису и не получая ключ доступа к API. В реальном приложении задержку удаляют, а функцию связывают с источником данных.
Теперь замените страницу каталога:
import { loadEvents } from "@/lib/load-events";
import { EventFilter } from "./event-filter";
export default async function EventsPage() {
const items = await loadEvents();
return (
<main>
<h1>Афиша</h1>
<EventFilter items={items} />
</main>
);
}await дожидается завершения функции и возвращает массив мероприятий. Здесь страница выполняется на сервере; клиентский фильтр получает уже подготовленные данные. Для async-функции страницы не добавляйте "use client".
Если Next.js готовит страницу заранее, эта задержка пройдет во время сборки. Поэтому в готовом приложении сообщение о загрузке может вообще не появиться. Подробнее об этом – в следующей статье.
Запрос HTTP и JSON
HTTP – протокол обмена между программами. Браузер или сервер отправляет запрос по адресу; другая сторона возвращает статус и тело ответа. API предоставляет способ обратиться к возможностям другой программы, например получить список мероприятий.
Самостоятельная функция ниже читает JSON по переданному полному адресу:
export async function readJson(url: string): Promise<unknown> {
const response = await fetch(url, { cache: "no-store" });
if (!response.ok) {
throw new Error(`Источник ответил HTTP ${response.status}`);
}
return response.json();
}fetch возвращает ответ, а response.json() читает его тело. Статусы 404 и 500 сами по себе не отклоняют Promise от fetch, поэтому проверяем response.ok. Сбой сети или неверный JSON тоже могут завершить функцию ошибкой.
unknown честно говорит, что структура результата пока неизвестна. Перед использованием нужно проверить поля. Запись as EventItem[] ничего не проверила бы во время выполнения. Для учебной афиши пока используем собственный подготовленный массив; проверку схемой Zod изучим рядом с формами.
Не подставляйте случайный адрес API: источник должен существовать и возвращать данные подходящей структуры. Если данные уже доступны серверной функции напрямую, ей не нужно делать HTTP-запрос к собственному обработчику сайта.
Когда данные могут устареть
Кеш – сохраненный результат, который можно использовать повторно. Это ускоряет ответ, но данные могут устареть. В примере cache: "no-store" явно запрашивает получение без сохранения в Data Cache.
В Next.js 16 запросы fetch не кешируются по умолчанию в Data Cache, но это не означает, что страница заново создается на сервере при каждом посещении: есть подготовка страницы и другие уровни кеширования. Поведение разработки тоже может отличаться от готовой сборки.
Механизм Cache Components включается отдельно через cacheComponents. Примеры этого курса не требуют его включения. Не смешивайте конфигурацию этого механизма с настройками другой модели кеширования. Когда появится задача обновлять афишу по расписанию, изучите кеширование и обновление кеша.
Где виден console.log
Вывод серверного компонента обычно смотрят в терминале сервера. Обработчик кнопки клиентского компонента выполняется в браузере, и его вывод виден в Console. Если сервер передал данные в браузер, пользователь может их увидеть. Поэтому не включайте секретные ключи в данные для интерфейса.
Попробуйте: временно верните из loadEvents пустой массив. Затем замените возвращение на throw new Error("Учебный сбой загрузки"). Это разные ситуации: отсутствие событий допустимо, сбой требует отдельного сообщения. Верните рабочий вариант перед продолжением.
Далее – состояния страницы. Руководство: получение данных.