Lesson 17 of 20

TypeScript with React

Typing React Components

TypeScript makes React development safer by typing props, state, and events. Use .tsx files for React components with TypeScript.

Example
// Props interface
interface ButtonProps {
  label: string;
  onClick: () => void;
  variant?: "primary" | "secondary";
  disabled?: boolean;
}

// Typed functional component
const Button: React.FC<ButtonProps> = ({ label, onClick, variant = "primary", disabled }) => {
  return (
    <button
      className={`btn btn-${variant}`}
      onClick={onClick}
      disabled={disabled}
    >
      {label}
    </button>
  );
};

Typing Hooks

TypeScript integrates well with React hooks, providing type safety for state and effects.

Example
import { useState, useEffect, useRef } from 'react';

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

function UserList() {
  // Typed state
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(false); // inferred boolean

  // Typed ref
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    async function fetchUsers() {
      setLoading(true);
      const res = await fetch('/api/users');
      const data: User[] = await res.json();
      setUsers(data);
      setLoading(false);
    }
    fetchUsers();
  }, []);

  return <div>{users.map(u => <p key={u.id}>{u.name}</p>)}</div>;
}

Typing Events & Forms

React event types are generic and need proper typing for type safety.

Example
function SearchForm() {
  const [query, setQuery] = useState('');

  // Typed event handler
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setQuery(e.target.value);
  };

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    console.log('Searching:', query);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input value={query} onChange={handleChange} />
      <button type="submit">Search</button>
    </form>
  );
}