Получение данных в Next.js

Получение данных в Next.js

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

Что такое получение данных?

Выборка данных - это просто способ получения данных. Данные могут быть получены из базы данных, файла JSON или другого программного обеспечения через API, и это может быть сделано во время рендеринга на стороне клиента, рендеринга на стороне сервера или генерации статического сайта.

Получение данных на стороне сервера, на стороне клиента или при генерации статического сайта может иметь некоторые преимущества:

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

Функции получения данных

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

Выборка данных на стороне клиента:

При выборке данных на стороне клиента данные выбираются на клиенте, например, в браузере, после отправки пользовательского интерфейса пользователю, даже когда в бэкэнд добавляются новые данные.Это снижает оптимизацию поисковых систем, поскольку пользовательский интерфейс отправляется пользователю без разметки макета. (HTML tags such as <a>, <p>, <h1>, etc. ), и когда данные получены, тогда делается разметка.


Для получения данных на стороне клиента в Next.js используются хуки useState и useEffect из React для рендеринга данных в браузере.

Выборка данных на стороне сервера:

При выборке данных на стороне сервера данные выбираются, пока пользовательский интерфейс все еще находится на локальной машине, прежде чем отобразить их пользователю. Каждый раз, когда данные добавляются или обновляются, пользовательский интерфейс запрашивает все данные снова, что означает, что при каждом обновлении браузера данные снова запрашиваются перед тем, как отобразить их пользователю. Пользовательский интерфейс создается на локальной машине благодаря фронтенд-библиотекам и фреймворкам, таким как React или Next.js, которые мы используем для создания пользовательского интерфейса. Наша локальная машина выступает в роли сервера. Сбор данных на стороне сервера в Next.js работает с помощью getServerSideProps для получения данных из базы данных или API в качестве бэкенда.

Генерация статических сайтов:

Для дальнейшего изложения давайте рассмотрим, что такое генерация статических сайтов. При генерации статического сайта предположим, что у вас есть пользовательский интерфейс, созданный на локальной машине, и API или база данных в качестве бэкенда, содержащая данные, которые должны быть отображены на пользовательском интерфейсе.
В этом сценарии данные предварительно извлекаются из бэкенда и отправляются в пользовательский интерфейс до того, как он будет отправлен пользователю. Допустим, мы добавляем новый контент в базу данных; предыдущие данные не нужно извлекать снова, поскольку они уже были предварительно извлечены. Вместо этого выполняется предварительная выборка новых данных и добавление их в пользовательский интерфейс перед отправкой пользователю. Это происходит потому, что предыдущие данные статически хранятся в пользовательском интерфейсе, отсюда и название ”генерация статических сайтов”, и это самый быстрый способ получения данных и отправки их пользователю. Генерация статических сайтов в Next js работает с getStaticProps и getStaticPaths для рендеринга статических страниц.

Когда использовать каждую функцию?

Когда необходим рендеринг на стороне клиента?

Когда поисковая оптимизация не нужна на вашем сайте, например, на приборной панели сайта.
Когда пользовательский интерфейс немного сложен.
Когда у сайта много пользователей.

Когда использовать рендеринг на стороне сервера?

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

Когда использовать генерацию статических сайтов?

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

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

Методы получения данных в Next.js

В Next.js для получения данных используются некоторые методы получения данных. К этим методам относятся;

useEffect и useState для выборки данных на стороне клиента.
getServerSideProps для получения данных на стороне сервера
getStaticProps для генерации статического сайта
getStaticPath для генерации статического сайта, который использует динамические маршруты.

Поэтому давайте узнаем, как их использовать. Для получения данных я использую внешний API под названием Fake Store API. Внешний API будет выступать для нас в качестве бэкенда или базы данных.

Использование метода получения данных на стороне клиента

Получить данные на стороне клиента довольно просто. Поэтому давайте рассмотрим, как получить данные на стороне клиента.

В папке pages вашего приложения Next.js создайте файл и назовите его index.js.

В файле index.js напишите следующий код. Сначала импортируйте useState и useEffect.

    import React from 'react'
    import { useEffect, useState } from 'react'

Затем создайте функцию и получите данные, используя URL-адрес API. В нашем случае мы используем API Fake Store, задаем данные в формате JSON и сохраняем их в состоянии. Мы также получим данные с помощью хука useEffect.

    export default function csr() {
        const [state, setState] = useState([]);
      async function getData() {
        const res = await fetch('https://fakestoreapi.com/products?limit=8');
        const data = await res.json();
        setState(data);
      }
      console.log('i am:',state);
      useEffect(() => {
        getData();
      }, [])

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

    return (
        <div>
          <h1> Welcome to My blog gallery ssg</h1>
          <div>
          {
            state.map((e) => (
                <a key={e.id}>
                <h2> {e.title} &rarr;</h2>
                <img src={e.image} width={250} height={200}/>
                <p>{e.description}</p>
                <h3>${e.price}</h3>
            </a>
            ))
            }
          </div>
        </div>
      )
    }

А затем запустите приложение.

Использование метода выборки данных на стороне сервера

Теперь давайте поработаем над получением данных на стороне сервера. Во-первых, давайте начнем с getServerSideProps;

Для начала создайте папку в папке pages в вашем приложении Next js.
Создайте файл с именем index.js, а затем напишите в нем приведенный ниже код;

    import React from 'react'
    export const getServerSideProps = async () => {
        const res = await fetch('https://fakestoreapi.com/products?limit=8');
        const data = await res.json();
        console.log(data);
        return{
          props: {product: data}
        }
    }
    const index = ({product}) => {
      return (
        <div>
          <h1> Welcome to My blog gallery ssg</h1>
            {product.map(item =>(
            <div key={item.id}>
                <a> <h3>{item.title}</h3> </a>
                <img src={item.url} />
            </div>
        ))}
        </div>
      )
    }
    export default index

В приведенном выше коде мы используем функцию getServerSideProps для получения данных. Я добавил console.log в функцию, чтобы вывести данные JSON из API. Таким образом, вы можете быть уверены, что данные получены из API. Вы можете удалить console.log; я использовал его только для тестирования.

При получении данных из URL мы устанавливаем ограничение, используя ?limit=8. Это ограничивает количество полученных данных до восьми. Вы можете установить любое число, если оно не превышает общее количество данных или количество элементов.

Самое важное, что нужно отметить, это то, что функция getServerSideProps() не записана в функции компонента, которая называется index. Вместо этого данные передаются как свойство в функцию компонента через возвращаемый объект.

    return {
      props:{product: data}
    }

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

    return {
      props:{data}
    }

Также следует отметить, что по умолчанию передается только функция компонента, но не функция getServerSideProps. Это относится и к другим функциям получения данных в Next js.

В функции компонента, после передачи свойства из getServerSideProps, мы отображаем данные с помощью функции map для получения каждого элемента.

(Не обращайте внимания на стилизацию в div или h1, вы можете использовать свою стилизацию).

Использование метода получения данных для генерации статических сайтов

В этом разделе вы узнаете, как использовать getStaticProps и getStaticPaths для генерации статического сайта.
Теперь давайте рассмотрим, как работает getStaticProps(). Честно говоря, это просто и похоже на использование getServerSideProps(), просто измените название функции.

    import React from 'react'
    
    export const getStaticProps = async () =>{
        const res = await fetch('https://fakestoreapi.com/products?limit=8');
        const data = await res.json()
        
        console.log(data)
        return {
            props: {blog: data}
        }
    }
    const index = ({ blog}) => {
      return (
        <div className={styles.div}>
          <h1 className={styles.header}> Welcome to My blog gallarey ssg</h1>
          <div className={styles.content}>
            {blog.map(item =>(
              <div className={styles.card} key={item.id}>
                <img src={item.image} width={200} height={200} />
                <div className={styles.text}>
                  <a> <h3>{item.title}</h3> </a>
                  <p> {item.description}</p>
                  <h3> ${item.price} </h3>
                </div>
              </div>
            ))}
          </div> 
        </div>
      )
    }
    export default index

Разница в том, что при загрузке страницы генерируется предварительно загруженная статическая страница, даже если элемент изменен из базы данных или, в нашем случае, URL API путем изменения ограничения числа на ?limit=7.
То есть, предварительно загруженная статическая страница на экране меняется немедленно, в отличие от getServerSideProps, в котором страницу необходимо обновить из браузера, чтобы показать обновленные данные. Это одно из различий между рендерингом на стороне сервера и генерацией статических сайтов.
Зная это, давайте рассмотрим генерацию статических путей.

Допустим, вы получаете и показываете список элементов на странице, и вам нужна возможность, при которой пользователь щелкает на любом элементе, и генерируется новая страница, которая отображает информацию о фактическом элементе, который был щелкнут, на основе id элемента. В этом случае вы можете использовать getStaticPaths.

Использование getStaticPaths немного запутанно для некоторых людей, поэтому я разложу это пошагово.

Во-первых, в папке pages вашего приложения Next js создайте папку с названием products. Мы будем использовать это название в качестве примера. На данный момент вы можете использовать любое имя, которое вы хотите использовать в нашем проекте.
В папке products создайте файл с именем index.js и еще один с именем [id].js. Этот файл будет использоваться в качестве динамического маршрута для каждого id товара. Вы можете даже назвать его [itemid].js, но для простоты остановитесь на первом, как на изображении ниже.

1

В файле index.js мы напишем следующий код для получения и отображения всех списков элементов/продуктов на странице. Мы сделаем это с помощью getStaticProps.

    import React from "react";
    import Link from "Next/link";
    export const getStaticProps = async () => {
      const res = await fetch("http://localhost:3000/api/data");
      const data = await res.json();
      return {
        props: { products: data },
        revalidate: 20,
      };
    };
    const index = ({ products }) => {
      return (
        <div>
          {products.map((product) => (
            <Link href={`products/${product.id}`}>
              <div key={product.id}>
                <h1>{product.title}</h1>
                <p>{[product.description]}</p>
              </div>
            </Link>
          ))}
        </div>
      );
    };
    export default index;

Теперь, чтобы сгенерировать статические страницы для отображения информации о каждом элементе на основе id, в файле [id].js мы получим данные с помощью getStaticProps().

    export const getStaticProps = async ({params}) => {
        const res = await fetch(`https://fakestoreapi.com/products/${params.id}`);
        const data = await res.json();
        console.log(params)
        console.log(data)
        return{
            props: {item: data}
        }
    }

Цель использования getStaticProps() здесь заключается в том, что Next js необходимо получить id каждого элемента, чтобы создать путь для отображения содержимого каждого элемента на основе его id на странице.
Параметр params используется в коде в качестве контекста.

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

    const product = ({item}) => {
      return (
        <>
            <Head>
                <title>
                    Products page
                </title>
            </Head>
            <h1>Product / Item</h1>
            <h2>{item.title}</h2>
            <img src={item.image} width={200} height={200}/>
            <p>{item.description}</p>
            <p>price: {item.price}</p>
        </>
      )
    }
    export default product

Над функцией компонента мы добавим функцию getStaticPaths для работы с путями.

    export const getStaticPaths = async () =>{
        const res = await fetch('https://fakestoreapi.com/products');
        const prod = await res.json();
        return{
            paths: prod.map(post => (
                {
                    params:{id: post.id.toString()}
                }
            )),
            fallback: true,
        }
    }

Данные извлекаются в приведенном выше коде, а ответ отправляется в формате JSON. В возвращаемом объекте мы используем paths, а не props, затем выполняем map через него, чтобы получить id в качестве параметров. Затем мы устанавливаем fallback в true. Если не установить fallback, это может привести к ошибке. Поэтому вы должны установить его.
Кроме того, мы получаем id динамически, а не жестко кодируем. Вы можете посмотреть в документации Next js, как это делается жестко.

Всегда передавайте параметры как строки, используя toString().

Весь исходный код файла [id].js будет выглядеть так, как показано ниже.

    import Head from 'next/head';
    import React from 'react'
    
    export const getStaticProps = async ({params}) => {
        const res = await fetch(`https://fakestoreapi.com/products/${params.id}`);
        const data = await res.json();
        console.log(params)
        console.log(data)
        return{
            props: {item: data}
        }
    }
    export const getStaticPaths = async () =>{
        const res = await fetch('https://fakestoreapi.com/products');
        const prod = await res.json();
        return{
            paths: prod.map(post => (
                {
                    params:{id: post.id.toString()}
                }
            )),
            fallback: true,
        }
    }
    const product = ({item}) => {
      return (
        <>
            <Head>
                <title>
                    Products page
                </title>
            </Head>
            <h1>Product / Item</h1>
            <h2>{item.title}</h2>
            <img src={item.image} width={200} height={200}/>
            <p>{item.description}</p>
            <p>price: {item.price}</p>
        </>
      )
    }
    export default product

Когда вы запустите свое приложение, вы можете изменить id из URL или щелкнув по списку, как показано на скринкасте ниже.

2

Заключение

Получение данных в Next js - это просто, хотя и может быть сложным, но если следовать основам и понимать их, то все получится. Надеюсь, эта статья поможет вам, когда вы захотите создать свой магазин электронной коммерции или сайт портфолио, где данные хранятся в базе данных или из API.