JavaRush /Курсы /Модуль 3: React /Передача данных из getServerSideProps в компоненты

Передача данных из getServerSideProps в компоненты

Модуль 3: React
13 уровень , 7 лекция
Открыта

Зачем передавать данные из getServerSideProps в компоненты?

Итак, давайте начнём с простого вопроса: зачем вообще передавать данные из getServerSideProps? Ответ: чтобы ваш компонент знал, какую информацию отображать.

getServerSideProps вызывается на сервере (или в среде выполнения SSR), обрабатывает запрос, получает данные и отправляет их на страницу как пропсы. Эти данные могут быть как простыми объектами, так и сложными структурами.

Представьте, что вы разрабатываете страницу профиля пользователя. Для этого вам нужно изначально получить данные пользователя с сервера (например, по API). Вот где пригодится getServerSideProps.

Разбор простого примера передачи данных

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

Что мы будем делать:

  1. Создадим страницу pages/post/[id].tsx.
  2. Используем getServerSideProps для получения поста по ID.
  3. Передадим данные поста как пропсы в компонент.

Вот код:

// pages/post/[id].tsx
import { GetServerSideProps } from 'next';

type PostProps = {
  post: {
    id: string;
    title: string;
    content: string;
  };
};

const PostPage = ({ post }: PostProps) => {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
};

// Реализация getServerSideProps
export const getServerSideProps: GetServerSideProps = async (context) => {
  const { id } = context.params as { id: string };

  // Симулируем запрос к API
  const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
  const post = await response.json();

  return {
    props: { post }, // Передаём данные в компонент
  };
};

export default PostPage;

Разберём код:

  1. getServerSideProps: получает параметр id из маршрута context.params и выполняет запрос к API для получения данных поста.

  2. props: возвращаем объект с ключом props, который содержит данные нашего поста. Next.js автоматически передаёт их в компонент страницы.

  3. Типизация: интерфейс PostProps описывает структуру пропсов, ожидаемых компонентом PostPage.

Когда пользователь откроет страницу /post/1, Next.js выполнит getServerSideProps, получит данные поста с ID 1 и передаст их в PostPage для рендеринга. Всё просто, как console.log("Hello, world!").

Важные моменты про передачу данных

  1. Передача сложных объектов: если данные, которые вы передаёте, содержат функции, Date или необычные структуры (например, Map, Set), они не будут корректно сериализованы. Помните: только JSON-совместимые структуры могут быть переданы через props.

    Пример данных, которые могут вызвать проблемы:

    const data = {
      date: new Date(), // Date объект
      map: new Map(),   // Map структура
    };
    

    Решение: преобразуйте сложные данные в строки или массивы:

    const serializedData = {
      date: data.date.toISOString(), // Преобразуем дату в строку
      map: Array.from(data.map.entries()), // Преобразуем Map в массив
    };
    
  2. Размер передаваемых данных: передаваемые через props данные добавляются в HTML-ответ сервера, что увеличивает размер страницы. Если данных действительно много, лучше загружать их на клиенте (клиентская пагинация, lazy loading и т.п.).

Управление данными в компоненте

Часто передача данных из getServerSideProps — это лишь первый шаг. Давайте разберем, как их можно использовать внутри нашего компонента.

  1. Рендеринг данных: как мы видели в примере выше, данные просто передаются через пропсы и рендерятся. Это стандартный подход.

  2. Работа с состоянием в компоненте: если данные нужно изменять на стороне клиента, можно использовать хук useState для управления ими. Например:

    const PostPage = ({ post }: PostProps) => {
      const [content, setContent] = React.useState(post.content);
    
      const updateContent = () => {
        setContent(content + " Еще немного текста...");
      };
    
      return (
        <div>
          <h1>{post.title}</h1>
          <p>{content}</p>
          <button onClick={updateContent}>Добавить текст</button>
        </div>
      );
    };
  3. Асинхронные операции на клиенте: если на стороне клиента нужно подгружать дополнительные данные, вы можете использовать useEffect и API-запросы:

    const PostPage = ({ post }: PostProps) => {
      const [comments, setComments] = React.useState([]);
    
      React.useEffect(() => {
        const fetchComments = async () => {
          const res = await fetch(`/api/comments/${post.id}`);
          const data = await res.json();
          setComments(data);
        };
    
        fetchComments();
      }, [post.id]);
    
      return (
        <div>
          <h1>{post.title}</h1>
          <p>{post.content}</p>
          <h2>Комментарии:</h2>
          <ul>
            {comments.map((comment) => (
              <li key={comment.id}>{comment.text}</li>
            ))}
          </ul>
        </div>
      );
    };

Типизация данных в компоненте

Мы уже упомянули типизацию пропсов, но давайте рассмотрим несколько полезных советов:

  1. Создавайте интерфейсы для данных:

    определение интерфейсов помогает поддерживать порядок в коде. Важно описывать не только сами пропсы, но и данные, которые вы получаете с сервера:
    interface Post {
      id: string;
      title: string;
      content: string;
    }
    
    interface PostProps {
      post: Post;
    }
  2. Проверяйте типы на уровне API: иногда API может вернуть данные неожиданной структуры (например, пропущенные поля). Используйте библиотеки вроде zod или io-ts для проверки данных перед их передачей в компонент.

    Пример использования с zod:

    import { z } from 'zod';
    
    const PostSchema = z.object({
      id: z.string(),
      title: z.string(),
      content: z.string(),
    });
    
    const post = await response.json();
    const parsedPost = PostSchema.parse(post);

Полезные паттерны

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

Контейнеры для логики: разделяйте логику получения и обработки данных от их отображения. Например, вы можете создать специальный контейнер-компонент, который передаёт данные в Dumb-компонент:

const PostContainer = ({ post }: PostProps) => {
  return <PostView post={post} />;
};

const PostView = ({ post }: PostProps) => {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
};

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

2
Задача
Модуль 3: React, 13 уровень, 7 лекция
Недоступна
Получение данных в getServerSideProps
Получение данных в getServerSideProps
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ