Introduction to React with TypeScript

What is React?

React is a JavaScript library developed by Facebook (now Meta) for building user interfaces. It allows developers to create reusable UI components and efficiently update the page when data changes. React uses a component-based architecture where you build encapsulated components that manage their own state, then compose them to make complex UIs.

At its core, React provides:

  • A component-based architecture
  • A virtual DOM for efficient updates
  • A declarative approach to UI development

Simple React component

// A simple React component
import React from "react";

function Greeting() {
  return <h1>Hello, world!</h1>;
}

export default Greeting;

Why React with TypeScript?

TypeScript adds static type checking to JavaScript, providing several benefits when combined with React:

  • Catch errors during development rather than at runtime
  • Better IDE support with intelligent code completion
  • Self-documenting code that clearly shows the shape of your data
  • Improved refactoring with type-safe operations

Core React Concepts

Components

Components are the building blocks of React applications. In modern React development, we use function components:

Function component

import React from "react";

// TypeScript interface defines the component props
interface GreetingProps {
  name: string;
  isLoggedIn?: boolean; // Optional prop
}

// Function component with typed props
function Greeting({ name, isLoggedIn = false }: GreetingProps) {
  return (
    <div>
      {isLoggedIn ? <h1>Welcome back, {name}!</h1> : <h1>Hello, {name}. Please sign in.</h1>}
    </div>
  );
}

export default Greeting;

Note: While React also supports class components, they are considered legacy. Modern React development focuses exclusively on function components with hooks, which provide a more concise and maintainable approach.

JSX

JSX is a syntax extension that allows you to write HTML-like code in your JavaScript:

function App() {
  const title = "Welcome to React";

  return (
    <div>
      <h1>{title}</h1>
      <p>This is JSX - JavaScript XML</p>
      {/* JSX allows embedding expressions */}
      <p>The current time is: {new Date().toLocaleTimeString()}</p>
    </div>
  );
}

When using TypeScript with React, we use the .tsx file extension.

Props

Props (short for "properties") are how components receive data from their parent:

// Parent component
function App() {
  return (
    <div>
      {/* Passing props to the Greeting component */}
      <Greeting name="Alice" isLoggedIn={true} />
      <Greeting name="Bob" />
    </div>
  );
}

// Child component receives props
interface GreetingProps {
  name: string;
  isLoggedIn?: boolean;
}

function Greeting({ name, isLoggedIn = false }: GreetingProps) {
  return <h1>{isLoggedIn ? `Welcome back, ${name}!` : `Hello, ${name}!`}</h1>;
}

State

State allows components to manage data that changes over time:

import { useState } from "react";

function Counter() {
  // State declaration with TypeScript type
  const [count, setCount] = useState<number>(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

Basic Hooks

Hooks are functions that let you use React features in function components:

import { useState, useEffect } from "react";

function Timer() {
  const [seconds, setSeconds] = useState<number>(0);

  useEffect(() => {
    // This runs after render and when dependencies change
    const interval = setInterval(() => {
      setSeconds((prevSeconds) => prevSeconds + 1);
    }, 1000);

    // Cleanup function runs before the component unmounts
    return () => clearInterval(interval);
  }, []); // Empty dependency array means this effect runs once

  return <p>Seconds elapsed: {seconds}</p>;
}

React and TypeScript Together

TypeScript enhances React development by providing type safety for:

Component Props

// Define the shape of props with an interface
interface ButtonProps {
  text: string;
  onClick: () => void;
  variant?: "primary" | "secondary"; // Union type for limited options
}

// Use the interface to type check props
function Button({ text, onClick, variant = "primary" }: ButtonProps) {
  return (
    <button className={`button ${variant}`} onClick={onClick}>
      {text}
    </button>
  );
}

Component State

import { useState } from "react";

// Type definition for our user
interface User {
  id: number;
  name: string;
  email: string;
}

function UserProfile() {
  // Specify the type for the state
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState<boolean>(true);

  // Type inference works automatically for primitive types
  const [count, setCount] = useState(0); // TypeScript infers number

  // Rest of the component...
}

Benefits for New React Developers

Starting with TypeScript from the beginning of your React journey provides several advantages:

  1. Clearer Component Contracts: TypeScript forces you to think about what data your components need
  2. Fewer Runtime Errors: Many common mistakes get caught during development
  3. Better Documentation: Types serve as built-in documentation for your code
  4. Enhanced IDE Experience: Get better autocomplete and inline errors

Conclusion

React with TypeScript creates a powerful development environment that combines React's efficient UI updates with TypeScript's type safety. While there's more to learn as you dive deeper, this foundation gives you the essential concepts to start building modern web applications.

In the next section, we'll cover how to set up a React project with TypeScript and build your first components.