Клиентские компоненты (Client Components)

Клиентские компоненты позволяют создавать интерактивный интерфейс, который может быть отрендерен на стороне клиента во время запроса. В Next.js клиентский рендеринг является опциональным, то есть вы должны явно указать, какие компоненты React должен рендерить на клиенте.

На этой странице рассматривается, как работают клиентские компоненты, как они рендерятся и когда их стоит использовать.

Преимущества клиентского рендеринга

Рендеринг на стороне клиента имеет несколько преимуществ, включая:

  • Интерактивность: Клиентские компоненты могут использовать состояние, эффекты и обработчики событий, что позволяет им мгновенно реагировать на действия пользователя и обновлять интерфейс.
  • Доступ к API браузера: Клиентские компоненты имеют доступ к API браузера, таким как геолокация или localStorage, что позволяет создавать интерфейсы для специфических сценариев использования.

Использование клиентских компонентов в Next.js

Чтобы использовать клиентские компоненты, добавьте директиву React "use client" в начало файла, перед импортами.

Директива "use client" объявляет границу между модулями серверных и клиентских компонентов. Это означает, что при определении "use client" в файле все импортируемые в него модули, включая дочерние компоненты, считаются частью клиентского бандла.

'use client'

import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>Вы кликнули {count} раз</p>
      <button onClick={() => setCount(count + 1)}>Нажми меня</button>
    </div>
  )
}
'use client'

import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>Вы кликнули {count} раз</p>
      <button onClick={() => setCount(count + 1)}>Нажми меня</button>
    </div>
  )
}

На диаграмме ниже показаны вложенные компоненты. Использование onClick и useState в toggle.js вызовет ошибку, если директива "use client" не определена. Это происходит потому, что по умолчанию компоненты рендерятся на сервере, где эти API недоступны. Определив директиву "use client" в toggle.js, вы указываете React рендерить компонент и его дочерние элементы на клиенте, где API доступны.

Директива Use Client и сетевая граница

Определение нескольких точек входа use client:

Вы можете определить несколько точек входа "use client" в дереве React-компонентов. Это позволяет разделить приложение на несколько клиентских бандлов (или ветвей).

Однако не нужно определять "use client" в каждом компоненте, который должен рендериться на клиенте. После определения границы все дочерние компоненты и импортируемые модули считаются частью клиентского бандла.

Как рендерятся клиентские компоненты?

В Next.js клиентские компоненты рендерятся по-разному в зависимости от того, является ли запрос частью полной загрузки страницы (первоначальный визит в приложение или перезагрузка страницы) или последующей навигации.

Полная загрузка страницы

Для оптимизации первоначальной загрузки страницы Next.js использует API React для рендеринга статического HTML-превью на сервере как для клиентских, так и для серверных компонентов. Это означает, что при первом посещении приложения пользователь сразу увидит содержимое страницы, не дожидаясь загрузки, парсинга и выполнения JavaScript-бандла клиентских компонентов.

На сервере:

  1. React рендерит серверные компоненты в специальный формат данных под названием React Server Component Payload (RSC Payload), который включает ссылки на клиентские компоненты.
  2. Next.js использует RSC Payload и инструкции JavaScript клиентских компонентов для рендеринга HTML маршрута на сервере.

Затем на клиенте:

  1. HTML используется для немедленного отображения быстрого неинтерактивного превью маршрута.
  2. React Server Components Payload используется для согласования деревьев клиентских и серверных компонентов и обновления DOM.
  3. Инструкции JavaScript используются для гидратации клиентских компонентов и придания их интерфейсу интерактивности.

Что такое гидратация?

Гидратация — это процесс присоединения обработчиков событий к DOM для придания статическому HTML интерактивности. Под капотом гидратация выполняется с помощью API React hydrateRoot.

Последующая навигация

При последующей навигации клиентские компоненты рендерятся полностью на клиенте, без серверного HTML.

Это означает, что JavaScript-бандл клиентских компонентов загружается и парсится. Как только бандл готов, React использует RSC Payload для согласования деревьев клиентских и серверных компонентов и обновления DOM.

Возврат в серверное окружение

Иногда после объявления границы "use client" может потребоваться вернуться в серверное окружение. Например, чтобы уменьшить размер клиентского бандла, получить данные на сервере или использовать API, доступные только на сервере.

Вы можете оставить код на сервере, даже если он теоретически вложен в клиентские компоненты, чередуя клиентские и серверные компоненты, а также серверные действия. Подробнее см. на странице Паттерны композиции.