0Pricing
React Academy · Lekcja

Formularze bezpieczne typowo i kontrakty odpowiedzi API

Używanie Zod do wyprowadzania typów TypeScript ze schematów oraz walidowania danych formularzy i odpowiedzi API.

Formularze bezpieczne typowo i kontrakty odpowiedzi API to bezpłatna lekcja React Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej React Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs React Academy zawiera 4 lekcji w sumie.

Dlaczego typowane struktury danych mają znaczenie

Formularze i odpowiedzi API to granice, na których dane trafiają do aplikacji z niezaufanych źródeł. Zod pozwala definiować schematy, które zarówno sprawdzają dane w czasie wykonywania, jak i pozwalają wywnioskować typy TypeScriptu.

Podstawy schematów Zod

Definiuj schematy za pomocą płynnego API biblioteki Zod. Użyj z.infer<typeof schema>, aby wyodrębnić typ TypeScriptu.

import { z } from 'zod';

const UserSchema = z.object({
  id: z.string().uuid(),
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().min(0).max(150).optional(),
  role: z.enum(['admin', 'user', 'guest']),
});

type User = z.infer<typeof UserSchema>;
// { id: string; name: string; email: string; age?: number; role: 'admin'|'user'|'guest' }

React Hook Form z resolverem Zod

Integruj schematy Zod z React Hook Form, aby zapewnić bezpieczną typowo walidację formularzy — TypeScript zna kształt danych formularza i błędów.

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';

const LoginSchema = z.object({
  email: z.string().email('Invalid email'),
  password: z.string().min(8, 'At least 8 characters'),
});
type LoginData = z.infer<typeof LoginSchema>;

function LoginForm() {
  const { register, handleSubmit, formState: { errors } } = useForm<LoginData>({
    resolver: zodResolver(LoginSchema),
  });

  const onSubmit = (data: LoginData) => {
    // data is LoginData — fully typed, already validated
  };
}

Walidowanie odpowiedzi API

Parsuj odpowiedzi API za pomocą Zod, aby wykrywać niezgodności struktury na granicy — jeśli API zwróci nieoczekiwane dane, aplikacja otrzyma szczegółowy błąd zamiast awarii w czasie wykonywania głęboko w komponencie.

async function fetchUser(id: string): Promise<User> {
  const res = await fetch(`/api/users/${id}`);
  const json = await res.json();
  return UserSchema.parse(json); // throws ZodError if shape is wrong
}

Bezpieczne parsowanie z obsługą błędów

Użyj schema.safeParse(), aby otrzymać obiekt wyniku zamiast wyjątku — to idealne rozwiązanie do walidacji formularzy, gdy należy wyświetlić użytkownikowi błędy.

const result = UserSchema.safeParse(formData);
if (!result.success) {
  const errors = result.error.flatten().fieldErrors;
  // { name: ['Must be at least 1 character'], email: ['Invalid email'] }
  return errors;
}
const user = result.data; // User — fully typed

Unie dyskryminowane z Zod

Należy użyć z.discriminatedUnion, aby modelować odpowiedzi API o różnych kształtach zależnie od flagi powodzenia lub błędu.

const ApiResponse = z.discriminatedUnion('ok', [
  z.object({ ok: z.literal(true), data: UserSchema }),
  z.object({ ok: z.literal(false), error: z.string(), code: z.number() }),
]);

type ApiResult = z.infer<typeof ApiResponse>;
// { ok: true; data: User } | { ok: false; error: string; code: number }

Transformacje w Zod

Należy użyć .transform(), aby wymusić określony typ lub zmienić kształt danych podczas parsowania — na przykład przekonwertować ciąg znaków z datą na obiekt Date.

const DateSchema = z.string().transform(s => new Date(s));
// Input: '2024-01-15' → Output: Date object

const EventSchema = z.object({
  title: z.string(),
  date: z.string().pipe(z.coerce.date()),
});
type Event = z.infer<typeof EventSchema>;
// { title: string; date: Date }

Ponowne używanie schematów

Należy wyprowadzać schematy tworzenia i aktualizacji ze schematu bazowego, aby uniknąć duplikowania kodu.

const UserSchema = z.object({ name: z.string(), email: z.string().email() });

// For creation: add password
const CreateUserSchema = UserSchema.extend({ password: z.string().min(8) });

// For update: all fields optional
const UpdateUserSchema = UserSchema.partial();

type CreateUser = z.infer<typeof CreateUserSchema>;
type UpdateUser = z.infer<typeof UpdateUserSchema>;

Server Action z Zod

Należy zwalidować dane formularza za pomocą Zod w Server Action Next.js przed odwołaniem do bazy danych.

async function createPost(formData: FormData) {
  'use server';
  const schema = z.object({ title: z.string().min(3), body: z.string().min(10) });
  const result = schema.safeParse(Object.fromEntries(formData));
  if (!result.success) return { errors: result.error.flatten().fieldErrors };
  await db.post.create({ data: result.data });
  revalidatePath('/blog');
  redirect('/blog');
}

Współdzielone schematy między frontendem a backendem

Należy eksportować schematy Zod ze współdzielonego pakietu, aby frontend i backend korzystały z tej samej logiki walidacji — jeden schemat jako jedyne źródło prawdy.

// packages/schemas/src/user.ts
export const CreateUserSchema = z.object({ ... });
export type CreateUser = z.infer<typeof CreateUserSchema>;

// Frontend imports:
import { CreateUserSchema, CreateUser } from '@company/schemas';
// Backend imports:
import { CreateUserSchema } from '@company/schemas';

Komunikaty błędów Zod

Należy dostosować komunikaty błędów dla poszczególnych pól, aby zapewnić lepsze wrażenia użytkownika — resolver automatycznie przekazuje je do wyświetlania błędów formularza.

const RegistrationSchema = z.object({
  username: z.string()
    .min(3, 'Username must be at least 3 characters')
    .max(20, 'Username cannot exceed 20 characters')
    .regex(/^[a-z0-9_]+$/, 'Only lowercase letters, numbers, and underscores'),
});

Szybki sprawdzian

Co zapewnia z.infer w TypeScript?

Podsumowanie

Należy zdefiniować schematy Zod raz i używać z.infer do wyprowadzania typów TypeScript. W React Hook Form należy używać zodResolver do bezpiecznej typowo walidacji. Odpowiedzi API należy parsować za pomocą Zod na granicy aplikacji, używać safeParse w przypadku błędów prezentowanych użytkownikowi oraz współdzielić schematy między frontendem a backendem za pośrednictwem wspólnego pakietu.

Często zadawane pytania

Czy lekcja „Formularze bezpieczne typowo i kontrakty odpowiedzi API” jest bezpłatna?

Tak — pełny tekst „Formularze bezpieczne typowo i kontrakty odpowiedzi API” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu React Academy, przejdź na CoddyKit PRO. Kurs React Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Formularze bezpieczne typowo i kontrakty odpowiedzi API”?

Używanie Zod do wyprowadzania typów TypeScript ze schematów oraz walidowania danych formularzy i odpowiedzi API. Ćwiczysz React Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć React Academy?

Nie wymagamy żadnego doświadczenia. React Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Formularze bezpieczne typowo i kontrakty odpowiedzi API”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji React Academy?

Tak. Każda lekcja React Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Rozłączne sumy dla wariantów komponentów
  2. Typy warunkowe i mapowane w React
  3. Komponenty polimorficzne z propsem 'as'
  4. Formularze bezpieczne typowo i kontrakty odpowiedzi API
← Powrót do React Academy