Какая проблема при вызове fetch напрямую в компоненте Next.js
Что проверяют
Различаете ли вы Server и Client Components и знаете ли, как сейчас устроено получение данных в App Router. Ответ про getServerSideProps выдаёт знания эпохи Pages Router. Следом обычно спрашивают про кэширование и про то, как не выстроить водопад запросов.
Как отвечать
Сначала уточните, о каком компоненте речь, потому что проблемы разные.
В Server Component прямой fetch это рекомендуемый способ: компонент объявляется async, данные попадают в HTML, секреты не уходят в браузер. Нюансы такие:
- кэширование: с Next.js 15
fetchпо умолчанию не кэшируется. Кэш включают явно:cache: 'force-cache',next: { revalidate: 60 }или директива'use cache'в режиме Cache Components; - блокировка рендера: некэшированный запрос задерживает всю страницу. Медленный блок оборачивают в
<Suspense>или добавляютloading.js, чтобы остальное пришло стримингом; - водопад: последовательные
awaitждут друг друга. Независимые запросы запускайте сразу и ждите черезPromise.all; - запрос к своему Route Handler: лишний HTTP-круг внутри того же сервера, а при статической сборке сервер ещё не запущен. Функцию доступа к данным вызывают напрямую.
Одинаковые fetch в одном рендере мемоизируются, поэтому запрос из layout и страницы уйдёт один раз.
В Client Component fetch прямо в теле функции выполняется на каждом рендере, а вместе с setState уходит в бесконечный цикл. В useEffect запрос стартует только после гидратации, контента нет в HTML, в dev со Strict Mode эффект срабатывает дважды, а при быстрой смене параметров старый ответ может перезаписать новый. Для клиентских данных берут TanStack Query или SWR: кэш, дедупликация и повторы там уже есть.
Где спотыкаются
Предлагают getStaticProps и getServerSideProps для App Router. Там их нет, данные получают прямо в серверных компонентах.
Считают, что fetch в серверном компоненте кэшируется навсегда. Так было в Next.js 14, сейчас по умолчанию наоборот.
Кладут ключ API в клиентский компонент или в переменную с префиксом NEXT_PUBLIC_, и он оказывается в бандле у каждого посетителя.