Получение и рендеринг постов Sanity на домашней странице

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

Создание клиента Sanity

Нам нужно создать способ, с помощью которого наше приложение сможет получать данные, которые мы храним в Sanity. К счастью, Sanity делает это очень просто. Подробнее о том, что я использую, вы можете прочитать здесь. Клиент Sanity

npm i -g @sanity/client
Вход в полноэкранный режим Выйти из полноэкранного режима

Это позволит установить клиент Sanity глобально для использования в любом проекте.
Нам нужно создать в корне папку lib и файл в этой папке sanity.js и вставить этот код в новый файл.

const sanityClient = require("@sanity/client");
const client = sanityClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
  apiVersion: "2021-03-25", // use current UTC date - see "specifying API version"!
  useCdn: true, // `false` if you want to ensure fresh data
});

export default client;
Вход в полноэкранный режим Выйти из полноэкранного режима

Этот код можно найти в документации пакета Sanity Client.


Получение постов

В вашем файле /pages/index.js (не в вашем /studio/schemas/index.js), в самом низу, вам нужно создать функцию async/await для получения данных.

export async function getStaticProps() {}
Вход в полноэкранный режим Выход из полноэкранного режима

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

import client from "../lib/sanity";
Войти в полноэкранный режим Выйти из полноэкранного режима

Вы можете, и должны, прочитать о getStaticProps здесь NextJS docs.
На этой странице объясняется, что делает эта функция, как она работает и когда ее использовать. Одна из причин использовать ее, если данные поступают из безголовой CMS, а именно так мы и планируем ее использовать.

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

export async function getStaticProps() {
  const query = `*[_type == "post"] | order(publishedAt desc) {
    _id,
    title,
    publishedAt,
    'slug': slug.current,
    body
  }`;

  const posts = await client.fetch(query);

  return {
    props: { posts },
  };
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

  • const query = `...`

    • Очевидно, что мы просто объявляем переменную для нашего запроса, чтобы использовать ее позже. Но здесь важен тот факт, что наш код в запросе окружен обратными тиками.
  • *[_type == "post"]

    • Это говорит нашему клиенту, что нужно взять каждую запись в нашей базе данных, которая имеет name post
    • Вы можете видеть, что мы назвали наши записи, когда создавали схему ‘Post’. Именно на это ссылается запрос "post".
  • | order(publishedAt desc)

    • Все достаточно просто, это говорит нашему запросу вернуть «посты», которые он нашел, в порядке убывания по дате публикации. Это означает, что самые новые посты возвращаются первыми.
 {
    _id,
    title,
    publishedAt,
    'slug': slug.current,
    body
  }
Вход в полноэкранный режим Выход из полноэкранного режима
  • Мы сообщаем запросу на выборку, какие данные мы хотим получить. В этом и заключается сила GROQ — вы получаете только те данные, которые вам нужны. Без этой части вы бы получили все данные ‘post’, которые выглядят примерно так.
{
    "_createdAt": "2022-07-17T00:48:06Z",
    "_id": "f026b8eb-0fc6-4a58-8494-789def2703ff",
    "_rev": "IvZ71YmXkO22WtmwIxDKV0",
    "_type": "post",
    "_updatedAt": "2022-07-17T00:48:06Z",
    "body": (5) [{…}, {…}, {…}, {…}, {…}],
    "publishedAt": "2022-07-17T00:45:31.070Z",
    "slug": {
        "_type": "slug",
        "current": "the-art-of-creating-a-post"
    },
    "title": "The art of creating a post"
}
Вход в полноэкранный режим Выход из полноэкранного режима

Это гораздо больше информации, чем нам нужно. Поэтому мы скажем нашему запросу возвращать нам только _id, title, publishedAt, slug и body.
Для любопытных, slug записывается как 'slug': slug.current, потому что, как вы можете видеть выше, slug возвращает объект, но нам нужно только значение current, а не _type. Поэтому мы возвращаем slug.current, но присваиваем его имени ключа slug.

  • const posts = await client.fetch(query);

    • Простой запрос на выборку, который использует client, который мы создали и импортировали в этом уроке, переменную query, которую мы только что добавили, и присваивает возврат новой переменной posts.
  • return { props: { posts } };

    • Возвращаем реквизит с нашей переменной posts, чтобы наш компонент мог ее использовать.

Рендеринг наших постов

Вернемся в начало нашего файла /pages/index.js, в котором мы сейчас находимся, и добавим нашу переменную posts, которую мы только что получили, в наш компонент Home.

export default function Home({ posts }) {
  return <h1>Hi :D</h1>;
}
Вход в полноэкранный режим Выход из полноэкранного режима

Мы можем извлечь данные posts из значения props с помощью метода destructuring.

Теперь создадим элементы HTML из нашего массива posts. Мы сделаем это путем сопоставления данных и сохранения их в переменной.

const postsElements = posts.map((post, index) => (
    <div key={index}>
      <p>{new Date(post.publishedAt).toDateString().slice(4)}</p>
      <h3>{post.title}</h3>
    </div>
  ));
Вход в полноэкранный режим Выйти из полноэкранного режима

Это вернет div с тегом p и h3 для каждого поста.
Нам нужен внешний div просто потому, что вам нужно, чтобы несколько элементов были обернуты в 1, чтобы вы могли вернуть его. Возвращение p и h3 без обертывания их во что-то приведет к ошибке. Мы также добавляем к этому key с index его позиции в массиве, чтобы React не кричал на нас. (об этом очень полезно почитать, это помогло мне много часов отлаживать, когда я начинал изучать React).

Мы добавляем тег p со значением publishedAt, превращенным в дату, в строку, чтобы HTML мог ее прочитать, и slice отделяем первые 4 символа строки (по сути, удаляя день недели).

И, наконец, h3 с title нашего поста.

Теперь, если вы добавите эту переменную в ваш return (обернув ее снова во внешний div по той же причине, что и выше, вы должны вернуть 1 внешний HTML-элемент), вот так.

return <div>{postsElements}</div>
Войти в полноэкранный режим Выход из полноэкранного режима

Закрыв текущий npm run dev и запустив его снова, вы увидите все ваши посты (но только заголовок и дату публикации) на главной странице по дате их публикации.

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


Будущие уроки

Вот и все для этой части. Возможно, я переборщил с объяснением каждой мелочи, но все эти понятия очень фундаментальны и будут использоваться в дальнейшем в этом проекте (и, скорее всего, в ваших будущих проектах). Поэтому я хотел помочь вам понять, как все работает, чтобы у вас было достаточно знаний, чтобы изучить и сделать что-то самостоятельно.

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


Ссылки

— Структура файла

— /pages/index.js

import client from "../lib/sanity";

export default function Home({ posts }) {
  const postsElements = posts.map((post, index) => (
    <div key={index}>
      <p>{new Date(post.publishedAt).toDateString().slice(4)}</p>
      <h3>{post.title}</h3>
    </div>
  ));
  return <div>{postsElements}</div>;
}

export async function getStaticProps() {
  const query = `*[_type == "post"] | order(publishedAt desc) {
    _id,
    title,
    publishedAt,
    'slug': slug.current,
    body
  }`;

  const posts = await client.fetch(query);

  return {
    props: { posts },
  };
}

Вход в полноэкранный режим Выход из полноэкранного режима

— /lib/sanity.js

const sanityClient = require("@sanity/client");
const client = sanityClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
  apiVersion: "2021-03-25", // use current UTC date - see "specifying API version"!
  useCdn: true, // `false` if you want to ensure fresh data
});

export default client;
Войти в полноэкранный режим Выход из полноэкранного режима

Оцените статью
devanswers.ru
Добавить комментарий