In this section, we will explore how to use TypeScript with React, a popular JavaScript library for building user interfaces. By combining TypeScript with React, you can leverage the benefits of static typing to catch errors early and improve the development experience.

Table of Contents

Introduction to React and TypeScript

React is a JavaScript library for building user interfaces, particularly single-page applications where you can create reusable UI components. TypeScript enhances JavaScript by adding static types, which can help catch errors during development and improve code quality.

Setting Up a React Project with TypeScript

To set up a new React project with TypeScript, you can use Create React App (CRA), which provides a simple way to create a React application with TypeScript support.

Steps:

  1. Install Node.js and npm: Ensure you have Node.js and npm installed on your machine.
  2. Create a new React project:
    npx create-react-app my-app --template typescript
    cd my-app
    npm start
    

This command sets up a new React project with TypeScript configuration. The --template typescript flag tells Create React App to use the TypeScript template.

TypeScript Basics in React

TypeScript Files

In a React project, TypeScript files use the .tsx extension for files that contain JSX (JavaScript XML) and .ts for regular TypeScript files.

Example Component

Here's a simple example of a functional component in TypeScript:

import React from 'react';

interface GreetingProps {
  name: string;
}

const Greeting: React.FC<GreetingProps> = ({ name }) => {
  return <h1>Hello, {name}!</h1>;
};

export default Greeting;

Explanation:

  • Interface: GreetingProps defines the type for the component's props.
  • React.FC: React.FC (or React.FunctionComponent) is a type provided by React for functional components.
  • Props Destructuring: The name prop is destructured from the props object.

Typing Props and State

Typing Props

Props are the inputs to a React component. You can define the types of props using TypeScript interfaces.

interface ButtonProps {
  label: string;
  onClick: () => void;
}

const Button: React.FC<ButtonProps> = ({ label, onClick }) => {
  return <button onClick={onClick}>{label}</button>;
};

Typing State

State is used to manage data within a component. You can define the state type using TypeScript.

import React, { useState } from 'react';

interface CounterState {
  count: number;
}

const Counter: React.FC = () => {
  const [state, setState] = useState<CounterState>({ count: 0 });

  const increment = () => setState({ count: state.count + 1 });

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

export default Counter;

Using Hooks with TypeScript

React hooks are functions that let you use state and other React features in functional components. TypeScript can be used to type these hooks.

useState Hook

const [count, setCount] = useState<number>(0);

useEffect Hook

import React, { useEffect } from 'react';

const Timer: React.FC = () => {
  useEffect(() => {
    const timer = setInterval(() => {
      console.log('Tick');
    }, 1000);

    return () => clearInterval(timer);
  }, []);

  return <div>Check the console for ticks</div>;
};

export default Timer;

Practical Example: Building a Todo App

Let's build a simple Todo application to demonstrate how to use TypeScript with React.

Step 1: Define Types

interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

type ToggleTodo = (selectedTodo: Todo) => void;
type AddTodo = (text: string) => void;

Step 2: Create Components

TodoList Component

import React from 'react';

interface TodoListProps {
  todos: Todo[];
  toggleTodo: ToggleTodo;
}

const TodoList: React.FC<TodoListProps> = ({ todos, toggleTodo }) => {
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id} onClick={() => toggleTodo(todo)}>
          {todo.text} {todo.completed ? '✔️' : '❌'}
        </li>
      ))}
    </ul>
  );
};

export default TodoList;

AddTodoForm Component

import React, { useState } from 'react';

interface AddTodoFormProps {
  addTodo: AddTodo;
}

const AddTodoForm: React.FC<AddTodoFormProps> = ({ addTodo }) => {
  const [text, setText] = useState<string>('');

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    addTodo(text);
    setText('');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
      />
      <button type="submit">Add Todo</button>
    </form>
  );
};

export default AddTodoForm;

Step 3: Combine Components in App

import React, { useState } from 'react';
import TodoList from './TodoList';
import AddTodoForm from './AddTodoForm';

const App: React.FC = () => {
  const [todos, setTodos] = useState<Todo[]>([]);

  const toggleTodo: ToggleTodo = (selectedTodo) => {
    const newTodos = todos.map(todo =>
      todo.id === selectedTodo.id ? { ...todo, completed: !todo.completed } : todo
    );
    setTodos(newTodos);
  };

  const addTodo: AddTodo = (text) => {
    const newTodo = { id: todos.length + 1, text, completed: false };
    setTodos([...todos, newTodo]);
  };

  return (
    <div>
      <TodoList todos={todos} toggleTodo={toggleTodo} />
      <AddTodoForm addTodo={addTodo} />
    </div>
  );
};

export default App;

Common Mistakes and Tips

Common Mistakes

  1. Incorrect Prop Types: Ensure that the prop types match the expected types in the component.
  2. State Initialization: Initialize state with the correct type.
  3. Event Types: Use the correct event types for event handlers (e.g., React.FormEvent, React.ChangeEvent).

Tips

  1. Use TypeScript's Type Inference: TypeScript can often infer types, reducing the need for explicit type annotations.
  2. Leverage TypeScript's Utility Types: Use utility types like Partial, Pick, and Omit to manipulate types.
  3. Use React.FC for Functional Components: This provides type checking and autocomplete for props.

Conclusion

In this section, we covered how to set up a React project with TypeScript, type props and state, use hooks with TypeScript, and build a practical Todo application. By using TypeScript with React, you can catch errors early and improve the overall development experience. In the next module, we will explore asynchronous programming in TypeScript.

© Copyright 2024. All rights reserved