JavaRush /Курсы /Модуль 3: React /Обработка данных с getServerSideProps и типизация данных

Обработка данных с getServerSideProps и типизация данных

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

Типизация данных в getServerSideProps

getServerSideProps — это функция, которая выполняется на сервере при каждом запросе к странице. Она позволяет получать данные ещё до того, как страница рендерится, и передаёт их в компонент страницы через пропсы.

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

import { GetServerSideProps } from 'next';

interface DataProps {
  message: string;
}

const HomePage: React.FC<DataProps> = ({ message }) => {
  return <h1>{message}</h1>;
};

export const getServerSideProps: GetServerSideProps = async () => {
  // Получение данных на сервере
  const data = { message: 'Hello from SSR!' };

  return {
    props: data, // Передаём данные в страницу
  };
};

export default HomePage;

Ключевой момент: безопасность

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

Почему важна типизация?

Когда вы работаете с данными, типизация помогает:

  1. Избежать ошибок при передаче данных в компонент.
  2. Улучшить автодополнение в редакторе.
  3. Сделать код читаемым и понятным для команды.

Пример без типизации:

export const getServerSideProps = async () => {
  const data = { message: 'без типизации' };
  return { props: data };
};

Попробуйте передать в компонент что-то нестандартное, например, объект или массив... и получите отлично типизированный хаос. Теперь давайте исправим это профессионально.

Как типизировать getServerSideProps?

Функция getServerSideProps из Next.js поддерживает типизацию через интерфейс GetServerSideProps. Давайте посмотрим, как это работает.

Пример с использованием интерфейсов:

import { GetServerSideProps } from 'next';

interface DataProps {
  message: string;
}

const DataPage: React.FC<DataProps> = ({ message }) => {
  return <div>{message}</div>;
};

export const getServerSideProps: GetServerSideProps<DataProps> = async () => {
  const data: DataProps = { message: 'Типизация работает!' };

  return {
    props: data,
  };
};

export default DataPage;

Здесь:

  • DataProps — интерфейс, описывающий структуру данных, которые возвращает getServerSideProps.
  • GetServerSideProps<DataProps> — типизация самой функции, которая указывает, что она возвращает пропсы такой структуры.

Обработка сложных данных

Если ваши данные более сложные, например, содержат массивы или вложенные объекты, вы можете расширить интерфейс:

interface NestedData {
  id: number;
  name: string;
}

interface ComplexDataProps {
  title: string;
  items: NestedData[];
}

export const getServerSideProps: GetServerSideProps<ComplexDataProps> = async () => {
  const data: ComplexDataProps = {
    title: 'Список элементов',
    items: [
      { id: 1, name: 'Элемент 1' },
      { id: 2, name: 'Элемент 2' },
    ],
  };

  return {
    props: data,
  };
};

Теперь вы уверены, что данные соответствуют структуре, и ошибки при передаче данных сведены к минимуму!

Обработка и передача данных на страницу

Когда данные приходят с API

Часто данные нужно запрашивать из внешнего API. Вот как это можно сделать:

export const getServerSideProps: GetServerSideProps = async () => {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();

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

Типизация ответа API

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

interface ApiResponse {
  id: number;
  name: string;
}

interface Props {
  items: ApiResponse[];
}

export const getServerSideProps: GetServerSideProps<Props> = async () => {
  const response = await fetch('https://api.example.com/items');
  const data: ApiResponse[] = await response.json();

  return {
    props: { items: data },
  };
};

const ItemPage: React.FC<Props> = ({ items }) => {
  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
};

export default ItemPage;

Управление ошибками

Что делать, если API вернул ошибку? Не паникуем. Вместо этого:

  1. Обрабатываем ошибки в getServerSideProps.
  2. Показываем пользователю понятное сообщение.
export const getServerSideProps: GetServerSideProps = async () => {
  try {
    const response = await fetch('https://api.example.com/endpoint');
    if (!response.ok) {
      throw new Error('Ошибка API');
    }

    const data = await response.json();
    return { props: { data } };
  } catch (error) {
    return { props: { error: 'Не удалось загрузить данные.' } };
  }
};

const ErrorPage: React.FC<{ data?: any; error?: string }> = ({ data, error }) => {
  if (error) return <div>{error}</div>;
  return <div>{JSON.stringify(data)}</div>;
};

export default ErrorPage;

Теперь, даже если API упадёт, ваш пользователь не увидит "белую страницу смерти".

Паттерны и оптимизация работы с данными

Работу с данными можно разделить на три ключевых этапа:

  1. Запрос данных — выбор, где и как запросить данные (API, база данных).
  2. Обработка данных — фильтрация, трансформация или выборка нужной информации.
  3. Передача данных — передача данных в компонент с минимальными изменениями.

Использование служб для запроса данных

Лучше выделить запрос данных в отдельную функцию для повторного использования:

// services/api.ts
export async function fetchItems(): Promise<ApiResponse[]> {
  const response = await fetch('https://api.example.com/items');
  if (!response.ok) throw new Error('Ошибка загрузки данных');
  return response.json();
}

// pages/items.tsx
import { fetchItems } from '../services/api';

export const getServerSideProps: GetServerSideProps = async () => {
  try {
    const items = await fetchItems();
    return { props: { items } };
  } catch {
    return { props: { items: [] } };
  }
};

Управление ошибками в getServerSideProps

Обработка ошибок важна особенно в условиях работы с сетевыми запросами. Если API упал или серверная логика вызвала исключение, у вас должен быть план "Б".

  1. Возвращайте заранее определённый интерфейс ошибок:
interface ErrorProps {
  error: true;
  message: string;
}

interface SuccessProps {
  error: false;
  data: ApiResponse[];
}

type Props = ErrorProps | SuccessProps;

export const getServerSideProps: GetServerSideProps<Props> = async () => {
  try {
    const data = await fetchItems();
    return { props: { error: false, data } };
  } catch {
    return { props: { error: true, message: 'Сбой загрузки данных' } };
  }
};

const ErrorHandlingPage: React.FC<Props> = (props) => {
  if (props.error) return <div>{props.message}</div>;

  return (
    <ul>
      {props.data.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
};
  1. Показывайте пользователю полезную информацию, а не пустую страницу.

Теперь вы вооружены полной типизацией и готовы творить безопасные, надёжные SSR-приложения!

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