Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Серверные и клиентские компоненты

В App Router каждый компонент по умолчанию серверный: он выполняется на сервере, а в браузер уходит только готовый HTML. Компонент с состоянием, эффектами или обработчиками событий должен работать в браузере — такой компонент называют клиентским и помечают директивой 'use client'.

Серверный компонент

Все страницы курса до сих пор были серверными. Поэтому страница статьи могла быть async и вызывать await getPost(slug):

// app/posts/[slug]/page.tsx
import { getPost } from '@/lib/posts';
 
export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const post = await getPost(slug);
  console.log('Читаем статью', slug);
 
  return <h1>{post?.title}</h1>;
}

Откройте /posts/hello-nextjs: сообщение «Читаем статью» появится в терминале, где запущен npm run dev, а не в консоли браузера. Код этого компонента в браузер не попадает.

Клиентский компонент

Кнопка «Нравится» хранит счётчик в состоянии, значит, ей нужен браузер. Создайте файл components/LikeButton.tsx:

// components/LikeButton.tsx
'use client';
 
import { useState } from 'react';
 
export default function LikeButton() {
  const [likes, setLikes] = useState(0);
 
  return <button onClick={() => setLikes(likes + 1)}>Нравится: {likes}</button>;
}

Директива 'use client' стоит в самой первой строке файла, до импортов. Она говорит Next.js: этот компонент и всё, что он импортирует, нужно отправить в браузер.

Как их сочетать

Серверный компонент может отрисовать клиентский:

// app/posts/[slug]/page.tsx (фрагмент)
import LikeButton from '@/components/LikeButton';
 
// ...внутри разметки статьи
<LikeButton />

На странице статьи появится кнопка, и счётчик будет расти при нажатии. Сама статья отрисована на сервере, в браузере оживает только кнопка.

Что где можно

ВозможностьСерверныйКлиентский
async и await в компонентеДаНет
Чтение базы данных и секретовДаНет
useState, useEffectНетДа
onClick, onChangeНетДа
window, localStorageНетДа

Передача данных

Серверный компонент передаёт клиентскому данные через свойства: <LikeButton initial={10} />. Значения должны превращаться в JSON — строки, числа, массивы, обычные объекты. Функцию передать нельзя, исключение — серверные действия из отдельного урока.

Сначала на сервере

Клиентский компонент тоже сначала отрисовывается на сервере в HTML, а затем в браузере React «оживляет» его — подключает обработчики. Этот процесс называют гидратацией.

Частая ошибка

Добавлять 'use client' в каждый файл «на всякий случай». Тогда весь код, включая работу с данными, уезжает в браузер, страница грузится дольше, а async-компоненты перестают работать. Помечайте только небольшие интерактивные части вроде кнопок и форм, а страницы оставляйте серверными.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.