Современная выборка данных в React с помощью TypeScript, React-Query и Zod

Хотя мой текущий стек основан на фантастическом стеке T3 Stack, использующем tRPC, я также являюсь ведущим frontend-разработчиком приложения на JavaScript React, созданного с помощью Create React App на основе Rails API. Перенося это приложение на TypeScript, я обнаружил, что жажду автоматической безопасности типов, которую обеспечивает tRPC.

К счастью, существует относительно простое решение проблемы взаимодействия с нетипизированными API в React на базе TypeScript.

Строительные блоки

Первой частью этой головоломки является невероятный React Query. Если вы еще не используете React Query в своем проекте, вам следует немедленно сделать шаг назад и спросить себя, почему. Выборка данных уже давно является спорной темой в React, а после появления хуков многие разработчики (в том числе и я) совершили ошибку, неправильно используя useEffect или создавая собственные библиотеки для выборки данных. Как и в случае с собственной системой аутентификации, это может вас подкосить.

Вторая часть — это Zod. Хотя существует множество библиотек валидации, Zod на данный момент является лидером, и вы должны использовать его, если только у вас нет абсолютной причины использовать что-то другое. Валидация Zod и способность легко выводить типы TypeScript станут ключом к типизации нашего нетипизированного API.

Собираем все вместе

Решение на удивление лаконично: Написать валидатор Zod для конечной точки API, использовать его для разбора ответа API и получить типизированный результат в React Query. Давайте рассмотрим пример этого на примере конечной точки API с информацией о пользователе:

// Schema for what the API endpoint should be returning
const UserSchema = z.object({
  id: z.number(),
  email: z.string().email(),
  displayName: z.string().min(1),
  role: z.enum(['USER', 'ADMIN']),
});

// Optionally, if you want to export this type to pass around
// elsewhere, you can export it:
export type User = z.infer<typeof UserSchema>;

// Query the endpoint and parse the response with Zod schema,
// which will type the response for us
const query = useQuery(["user"], async () => {
  const response = await (await fetch('/me')).json();
  return UserSchema.parse(response);
});

query.data // will be typed
Вход в полноэкранный режим Выйти из полноэкранного режима

Вот и все! Результирующий query.data будет типизирован либо как схема, либо как undefined (поскольку запросы могут быть неудачными). Если ответ от API не пройдет валидацию, вы получите ошибку, с которой можно разобраться в процессе разработки или даже поймать в продакшене с помощью инструмента регистрации исключений, который вы используете.

Хотя это решение не такое автоматическое, как tRPC, и требует написания некоторого количества шаблонов, оно хорошо масштабируется и делает работу с нетипизированными конечными точками API менее болезненной в TypeScript.

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