Books/TypeScript Essentials/TypeScript for Frontend (React)

    TypeScript for Frontend (React)

    TypeScript for Frontend (React)

    When you ask AI to build a frontend, it will almost always generate React with TypeScript. This tutorial covers the TypeScript patterns specific to React that you'll see in every AI-generated component.

    React Component Files: .tsx

    React components that contain JSX (the HTML-like syntax) use the .tsx file extension:

    • .ts — TypeScript without JSX
    • .tsx — TypeScript with JSX (React components)

    Component Props

    Props are how you pass data to React components. TypeScript defines what props a component accepts:

    // Define the props
    interface ButtonProps {
      label: string;
      onClick: () => void;
      variant?: "primary" | "secondary";
    }
    
    // Use the props in a component
    const Button = ({ label, onClick, variant = "primary" }: ButtonProps) => {
      return (
        <button className={variant} onClick={onClick}>
          {label}
        </button>
      );
    };
    
    // Using the component
    <Button label="Click me" onClick={() => console.log("clicked!")} />
    <Button label="Cancel" onClick={handleCancel} variant="secondary" />

    This is the #1 pattern you'll see. Every component has a Props interface defining what it accepts.

    What to ask your AI: "Create a [Card / Modal / Form] component. Here are the props I need: [list them]."

    Children Props

    Some components wrap other content:

    interface ContainerProps {
      children: React.ReactNode;    // Can contain any JSX
      className?: string;
    }
    
    const Container = ({ children, className }: ContainerProps) => {
      return <div className={className}>{children}</div>;
    };
    
    // Usage
    <Container className="my-class">
      <h1>Hello</h1>
      <p>Any content here</p>
    </Container>

    React.ReactNode means "anything that can be rendered" — text, elements, components, etc.

    State with useState

    useState is how React components manage data that changes. TypeScript types the state:

    import { useState } from "react";
    
    const Counter = () => {
      // TypeScript infers the type from the initial value
      const [count, setCount] = useState(0);           // number
      const [name, setName] = useState("");             // string
      const [isOpen, setIsOpen] = useState(false);      // boolean
    
      // Sometimes you need to specify the type explicitly
      const [user, setUser] = useState<User | null>(null);
      const [items, setItems] = useState<Product[]>([]);
      const [error, setError] = useState<string | null>(null);
    };

    Key pattern: when the initial value is null or an empty array, TypeScript needs help knowing the full type:

    • useState<User | null>(null) — "this will be a User or null"
    • useState<Product[]>([]) — "this will be an array of Products"

    What to ask your AI: "I need a component that manages a list of [items]. Set up the state with proper TypeScript types."

    Event Handling

    React events have TypeScript types. Here are the most common:

    // Click event
    const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
      console.log("Button clicked");
    };
    
    // Form submit
    const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
      event.preventDefault();
      // process form...
    };
    
    // Input change
    const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
      setName(event.target.value);
    };
    
    // Select change
    const handleSelect = (event: React.ChangeEvent<HTMLSelectElement>) => {
      setCategory(event.target.value);
    };

    Don't memorize these. The pattern is always React.[EventType]<HTML[Element]Element>.

    What to ask your AI: "What's the correct TypeScript type for an onChange handler on a textarea?"

    Fetching Data with useEffect

    A very common pattern — fetch data when a component loads:

    import { useState, useEffect } from "react";
    
    interface User {
      id: number;
      name: string;
      email: string;
    }
    
    const UserProfile = ({ userId }: { userId: number }) => {
      const [user, setUser] = useState<User | null>(null);
      const [loading, setLoading] = useState(true);
      const [error, setError] = useState<string | null>(null);
    
      useEffect(() => {
        const fetchUser = async () => {
          try {
            const response = await fetch(`/api/users/${userId}`);
            const data: User = await response.json();
            setUser(data);
          } catch (err) {
            setError("Failed to load user");
          } finally {
            setLoading(false);
          }
        };
    
        fetchUser();
      }, [userId]);
    
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error: {error}</p>;
      if (!user) return null;
    
      return (
        <div>
          <h1>{user.name}</h1>
          <p>{user.email}</p>
        </div>
      );
    };

    This pattern (loading/error/data states) appears in almost every component that fetches data.

    What to ask your AI: "Create a component that fetches [data] from [endpoint] and displays it. Include loading and error states."

    Common React + TypeScript Patterns

    Form with Multiple Fields

    interface FormData {
      name: string;
      email: string;
      message: string;
    }
    
    const ContactForm = () => {
      const [formData, setFormData] = useState<FormData>({
        name: "",
        email: "",
        message: "",
      });
    
      const handleChange = (
        event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
      ) => {
        const { name, value } = event.target;
        setFormData((prev) => ({ ...prev, [name]: value }));
      };
    
      const handleSubmit = (event: React.FormEvent) => {
        event.preventDefault();
        // Submit formData...
      };
    
      return (
        <form onSubmit={handleSubmit}>
          <input name="name" value={formData.name} onChange={handleChange} />
          <input name="email" value={formData.email} onChange={handleChange} />
          <textarea name="message" value={formData.message} onChange={handleChange} />
          <button type="submit">Send</button>
        </form>
      );
    };

    List Rendering

    interface Todo {
      id: number;
      text: string;
      completed: boolean;
    }
    
    const TodoList = ({ todos }: { todos: Todo[] }) => {
      return (
        <ul>
          {todos.map((todo) => (
            <li key={todo.id} className={todo.completed ? "done" : ""}>
              {todo.text}
            </li>
          ))}
        </ul>
      );
    };

    Conditional Rendering

    interface AlertProps {
      type: "success" | "error" | "warning";
      message: string;
      onDismiss?: () => void;
    }
    
    const Alert = ({ type, message, onDismiss }: AlertProps) => {
      return (
        <div className={`alert alert-${type}`}>
          <p>{message}</p>
          {onDismiss && <button onClick={onDismiss}>Dismiss</button>}
        </div>
      );
    };

    Prompts for Building Frontend with AI

    Here are ready-to-use prompts for asking AI to build React components:

    Layout & Pages:

    • "Create a responsive navigation bar with links to Home, About, and Contact pages. Include a mobile hamburger menu."
    • "Build a dashboard page with a sidebar, header, and main content area using TypeScript and Tailwind CSS."

    Forms:

    • "Build a signup form with name, email, password, and confirm password fields. Add validation that shows errors below each field."
    • "Create a multi-step form wizard with 3 steps. Each step should validate before allowing the user to proceed."

    Data Display:

    • "Create a product listing page that fetches products from /api/products and displays them in a responsive grid of cards."
    • "Build a data table component that supports sorting by column and pagination."

    Interactive Components:

    • "Build a modal component that opens when a button is clicked and closes when clicking outside or pressing Escape."
    • "Create a search bar with debounced input that filters a list of items as the user types."

    What's Next?

    You've seen TypeScript for the frontend. The next tutorial covers TypeScript for Backend (Node.js) — API routes, database operations, and server-side patterns.


    🌐 www.genai-mentor.ai