DevGang
Авторизоваться

Next.js 13. Получение данных с помощью App Router

В новом выпуске Next.js 13 появились новые парадигмы и концепции. Представлена одна распространенная концепция react и next.js.— это серверные компоненты, то есть компоненты, отображаемые на сервере. Это позволяет ускорить загрузку страниц и улучшить SEO.

Это отличная концепция, позволяющая выполнять асинхронные задачи на компоненте реагирования, например получение данных. Это значит, что вам не понадобится useEffect для получения данных из API; это считается анти-шаблоном в реакции, когда дело доходит до получения данных на клиенте с помощью useEffect, потому что это может вызвать некоторые дорогостоящие проблемы в долгосрочной перспективе, если вы не будете осторожны с ним.

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

Для SEO и производительности гораздо лучше получать данные на сервере, и Next.js 13 облегчает это выполнение. В этой статье мы рассмотрим, как извлекать данные с помощью нового Next.js 13 App Router, а также несколько советов и хитростей.

Решение 1. Получение данных с помощью серверных компонентов fetch и React

Это очень просто: создайте асинхронный компонент, извлеките данные с fetch на верхнем уровне, а затем получите доступ к данным в шаблоне.

// app/page.jsx

export default async function Page() {
  const res = await fetch("https://jsonplaceholder.typicode.com/posts");
  const posts = await res.json();

  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

Вот и все! Он будет извлекать данные на сервере и отображать html-страницу с уже извлеченными данными. Если вы хотите повторно подтвердить или перепроверить данные, Next.js расширяет fetch, где фреймворк позволяет вам настраивать поведение кэширования и повторной проверки для каждого запроса на сервере.

В предыдущем примере мы можем еще больше улучшить fetch api, добавив свойство revalidate к объекту response и выполнив обработку ошибок.

Допустим, мы хотим повторно проверять данные каждые 1 час.

// app/page.jsx

export default async function Page() {
  const res = await fetch("https://jsonplaceholder.typicode.com/posts", {
    next: { revalidate: 3600 }, // Will revalidate every 1 hour
  });
  const posts = await res.json();

  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

После этого мы можем добавить оператор throw, чтобы выдать ошибку, если статус ответа не равен 200.

// app/page.jsx

export default async function Page() {
  const res = await fetch("https://jsonplaceholder.typicode.com/posts", {
    next: { revalidate: 3600 }, // Will revalidate every 1 hour
  });

  if (!res.ok) {
    // This will activate the closest `error.js` Error Boundary.
    throw new Error(`Failed to fetch the data`)
  }
  const posts = await res.json();

  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  )
}

Но что, если вам действительно нужно получить данные о клиенте? Вот тут-то и появляется второе решение.

Решение 2: Извлечение данных в клиенте с помощью сторонних библиотек

Как я уже сказал, лучше извлекать данные на сервере для SEO и повышения производительности, потому что данные, которые будут извлечены, также будут включены в HTML.

Но если требуется выборка данных на стороне клиента, сначала рассмотрите возможность использования сторонней библиотеки, такой как SWR и React Query, чтобы избежать использования useEffect.

Это связано с тем, что в этих библиотеках уже включены крайние случаи, такие как дедупликация запросов, кэширование ответов, предотвращение сетевых водопадов, отражение, мутация и т.д.

Давайте посмотрим, как это выглядит, когда вы хотите получить данные с помощью SWR.

SWR - это библиотека выборки данных, созданная vercel, которая является гораздо более простым решением по сравнению с react query.

Допустим, мы хотим получить данные в клиентском компоненте.

// components/profile.tsx
import { getProfileById } from '@/lib/actions'; // Example import

export function Profile({id}: {id: string}) {
     const { data, error, isLoading } = useSWR([`/api/profile/`, id], ([url, userId]) => getProfileById(url, userId))

    if (error) return <div>failed to load</div>

    if (isLoading) return <div>Loading...</div>

    return <div>hello, {data?.name}</name>
}

Это выглядит похоже, но разница в том, что он извлекается непосредственно в браузере. Если вы посмотрите на разницу между сетевыми запросами в ваших devtools, вы увидите, что запрос выполняется.

Улучшение извлечения данных с Suspense

Это может быть дополнительно улучшено с помощью компонента Suspense. Приостановка в react - это компонент, который заменяет резервный компонент до тех пор, пока дочерние элементы, обернутые вокруг него, не завершат загрузку.

Мы можем сделать это с помощью следующего примера:

// components/profile.tsx
'use client'

import { getProfileById } from '@/lib/actions'; // Example import


export function Profile({ id }: { id: string }) {
    const { data, error, isLoading } = useSWR([`/api/profile/`, id], ([url, userId]) => getProfileById(url, userId), { suspense: true })

    return <div>hello, {data.name}</name>
}

затем, app/page.tsx:

// app/page.tsx
'use client'

import { Suspense } from 'react'
import { Skeleton } from '@/components/ui/skeleton' // Example
import { Profile } from '@/components/profile'
import { ErrorBoundary } from 'react-error-boundary' // npm install react-error-boundary

export default function Page() {
  return (
    <ErrorBoundary fallback={<h2>Could not fetch profile</h2>}>
      <Suspense fallback={<Skeleton />}>
        <Profile />
      </Suspense>
    </ErrorBoundary>
  )
}

Это выглядит намного чище и на самом деле не требует использования дополнительного оператора цепочки и условных проверок.

ВАЖНАЯ ЗАМЕТКА

React Suspense все еще находится в стадии эксперимента, когда дело доходит до извлечения данных, но команда реагирования работает над тем, как правильно обрабатывать приостановку, когда дело доходит до извлечения данных.
React Suspense НЕ обнаруживает, когда данные извлекаются внутри > обработчика эффекта или события.

Советы и приемы

Вот несколько полезных советов и приемов, касающихся получения данных в React.

  1. Насколько это возможно, избегайте выборки данных на клиенте.
  2. Избегайте использования useEffect для выборки данных, используйте самоуверенную библиотеку выборки данных, чтобы использовать весь потенциал того, что может предложить react при обработке асинхронных данных.
  3. По моему мнению, добавление «использовать клиент» в page.tsx или layout.tsx считается плохой практикой, потому что в идеале они должны отображаться на сервере.
  4. При работе с полями поиска или входными данными полезно рассмотреть возможность использования методов устранения дребезга или регулирования, чтобы уменьшить количество запросов и избежать злоупотребления API.

Заключение

В этой статье мы узнали, как мы можем получать данные в новом маршрутизаторе приложений Next.js на сервере и клиенте. Мы также кратко обсудили react suspense и то, как мы можем использовать его для отображения данных о загрузке.

Надеюсь, вы узнали что-то из этой статьи и примените это в своих текущих и новых проектах.

Источник:

#JavaScript #React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу