Lädt...

🔧 Building Robust Applications in React with TypeScript and Zod for REST API Validation


Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to

When building applications with React and TypeScript, leveraging TypeScript's static typing capabilities can significantly enhance your code's reliability. However, even with TypeScript, you can't guarantee the shape and type of data coming from external APIs. This potential discrepancy can lead to runtime errors that disrupt your application's functionality. In this blog post, we'll explore how to handle such situations using Zod, a TypeScript-first schema declaration and validation library.

Scenario: Fetching User Data with TypeScript

Imagine you have a React application that fetches user data from an API. The User object has a phoneNumber property, which is expected to be a string. You'll format this phone number to display it in a user-friendly manner. Here's how you might start:

// types.ts
export interface User {
  id: number;
  name: string;
  phoneNumber: string;
}

// api.ts
export const fetchUser = async (userId: number): Promise<User> => {
  const response = await fetch(`https://api.example.com/users/${userId}`);
  const data: User = await response.json();
  return data;
};

// UserComponent.tsx
import React, { useEffect, useState } from 'react';
import { User } from './types';
import { fetchUser } from './api';

const UserComponent: React.FC<{ userId: number }> = ({ userId }) => {
  const [user, setUser] = useState<User | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    fetchUser(userId)
      .then(setUser)
      .catch(err => setError(err.message));
  }, [userId]);

  if (error) return <div>Error: {error}</div>;
  if (!user) return <div>Loading...</div>;

  const formattedPhoneNumber = formatPhoneNumber(user.phoneNumber);

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Phone: {formattedPhoneNumber}</p>
    </div>
  );
};

const formatPhoneNumber = (phoneNumber: string): string => {
  // Logic to format the phone number
  return phoneNumber.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
};

export default UserComponent;

In this example, we expect phoneNumber to be a string. However, if the backend changes phoneNumber to a number, this will lead to a runtime error in the formatPhoneNumber function.

Runtime Error Example

Suppose the backend now sends:

{
  "id": 1,
  "name": "John Doe",
  "phoneNumber": 1234567890
}

This change will cause a runtime error in the formatPhoneNumber function because replace is not a method on numbers. The error will look like this:

TypeError: phoneNumber.replace is not a function

This error indicates that phoneNumber is not a string as expected, but a number, leading to the failure of the replace method.

Introducing Zod for Schema Validation

To safeguard against such issues, we can use Zod to validate the data we receive from the API. Here's how we can do it step-by-step:

  1. Install Zod :
npm install zod
  1. Define a Zod Schema :
// schema.ts
import { z } from 'zod';

export const userSchema = z.object({
  id: z.number(),
  name: z.string(),
  phoneNumber: z.string(),
});

export type User = z.infer<typeof userSchema>;
  1. Validate API Response and Provide Feedback :
// api.ts
import { userSchema, User } from './schema';

export const fetchUser = async (userId: number): Promise<User> => {
  const response = await fetch(`https://api.example.com/users/${userId}`);
  const data = await response.json();

  const result = userSchema.safeParse(data);

  if (!result.success) {
    console.error("Validation Error:", result.error.format());
    throw new Error('Invalid data format');
  }

  return result.data;
};
  1. Handle Validation in the Component :
// UserComponent.tsx
import React, { useEffect, useState } from 'react';
import { User } from './schema';
import { fetchUser } from './api';

const UserComponent: React.FC<{ userId: number }> = ({ userId }) => {
  const [user, setUser] = useState<User | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    fetchUser(userId)
      .then(setUser)
      .catch(err => setError(err.message));
  }, [userId]);

  if (error) return <div>Error: {error}</div>;
  if (!user) return <div>Loading...</div>;

  const formattedPhoneNumber = formatPhoneNumber(user.phoneNumber);

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Phone: {formattedPhoneNumber}</p>
    </div>
  );
};

const formatPhoneNumber = (phoneNumber: string): string => {
  // Logic to format the phone number
  return phoneNumber.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
};

export default UserComponent;

In this updated example, the fetchUser function uses the Zod schema to validate the API response. If the data doesn't match the expected schema, an error is thrown, and a detailed validation error is logged to the console. This feedback helps developers quickly identify and resolve issues with the API data.

Error Message Example

With the Zod validation in place, if the backend sends the phoneNumber as a number, the application will catch this discrepancy and throw an error. The console will log a detailed error message like this:

Validation Error: {
  "phoneNumber": {
    "_errors": ["Expected string, received number"]
  }
}

In addition to logging the error, the application will throw an error to the user with the message:

Error: Invalid data format

This message indicates to the user that there was an issue with the data received from the API.

Conclusion

Using Zod for schema validation in your React and TypeScript applications ensures that your application can gracefully handle unexpected changes in the API response structure. This approach helps you catch potential issues early, leading to more robust and reliable applications. By incorporating Zod into your development workflow, you can enhance your application's resilience against API changes and reduce runtime errors.

Remember, while TypeScript provides excellent compile-time type checking, runtime validation with tools like Zod is essential for dealing with external data sources. This combination ensures that your application remains stable and predictable, even when the data it relies on changes unexpectedly.

...

🔧 Building Robust Applications in React with TypeScript and Zod for REST API Validation


📈 81.21 Punkte
🔧 Programmierung

🔧 Building a Robust API Layer with TypeScript, Tanstack Query, Zod, and Zodios


📈 52.37 Punkte
🔧 Programmierung

🔧 Building CRUD App with react-form, zod, react data grid, react-query and json-server


📈 42.94 Punkte
🔧 Programmierung

🔧 API Validation in Next.js 15 with Zod and TypeScript


📈 40.84 Punkte
🔧 Programmierung

🔧 Creating Dynamic Forms with React, Typescript, React Hook Form and Zod


📈 40.38 Punkte
🔧 Programmierung

🔧 Making a REST API typesafe with React Query and Zod


📈 40.36 Punkte
🔧 Programmierung

🔧 Zod Validation in [React + Typescript]


📈 40.05 Punkte
🔧 Programmierung

🔧 Introducing the Zod Schema Designer: A Visual Tool for Creating and Editing Zod Schemas


📈 39.32 Punkte
🔧 Programmierung

🔧 Building React Forms with Ease Using React Hook Form, Zod and Shadcn


📈 37.28 Punkte
🔧 Programmierung

🔧 How to Use Zod for React API Validation


📈 36.43 Punkte
🔧 Programmierung

🔧 Exploring Zod and the Benefits of Schema-Based Validation in TypeScript Projects


📈 35.75 Punkte
🔧 Programmierung

🔧 Full-Stack Next.js 15 Development Using Zod, Typescript, tRPC, react-query, and Sequelize ORM


📈 34.72 Punkte
🔧 Programmierung

🔧 Full-Stack Next.js 15 Development Using Zod, Typescript, tRPC, react-query, and Sequelize ORM


📈 34.72 Punkte
🔧 Programmierung

🔧 How to create a contact form with EmailJS, Zod, ShadCN UI, TypeScript using React and NextJS.


📈 34.72 Punkte
🔧 Programmierung

🔧 Building a TypeScript Helper for Mock Data Generation with Zod and Faker


📈 34.67 Punkte
🔧 Programmierung

🔧 Zod for TypeScript Schema Validation: A Comprehensive Guide


📈 34.39 Punkte
🔧 Programmierung

🔧 Zod vs. Valibot: Which Validation Library is Right for Your TypeScript Project?


📈 34.39 Punkte
🔧 Programmierung

🔧 Understanding Zod: A Comprehensive Guide to Schema Validation in JavaScript/Typescript


📈 34.39 Punkte
🔧 Programmierung

🔧 Master schema validation in TypeScript with Zod


📈 34.39 Punkte
🔧 Programmierung

🔧 Zod 101 - A Typescript-first Schema Validation Library


📈 34.39 Punkte
🔧 Programmierung

🔧 How to validate your Next.js API with Zod and Typescript


📈 34.15 Punkte
🔧 Programmierung

🔧 Building a Robust API Layer - `api-def` Package Integration with React (NextJs) app


📈 34.07 Punkte
🔧 Programmierung

🔧 Expo, React Hook Form + TypeScript❤️ + Zod


📈 33.36 Punkte
🔧 Programmierung

🔧 Form Validation In TypeScipt Projects Using Zod and React Hook Form


📈 32.69 Punkte
🔧 Programmierung

🔧 Simplifying Form Validation with Zod and React Hook Form


📈 32.69 Punkte
🔧 Programmierung

🔧 Four Essential Tips for Building a Robust REST API in Java


📈 32.58 Punkte
🔧 Programmierung

🔧 Ensuring Robust React Applications: A Deep Dive into Testing with Jest and React Testing Library


📈 32.5 Punkte
🔧 Programmierung

🔧 Building a reusable multi-step form with React Hook Form and Zod


📈 31.62 Punkte
🔧 Programmierung

🔧 Leveraging Zod for Form Validation in React: Unleashing the Power of superRefine


📈 31.34 Punkte
🔧 Programmierung

🔧 Building Robust Applications with Real-Time Email Verification API: A Developer's Guide


📈 30.54 Punkte
🔧 Programmierung