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:
- Install Node.js and npm: Ensure you have Node.js and npm installed on your machine.
- 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
(orReact.FunctionComponent
) is a type provided by React for functional components. - Props Destructuring: The
name
prop is destructured from theprops
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
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
- Incorrect Prop Types: Ensure that the prop types match the expected types in the component.
- State Initialization: Initialize state with the correct type.
- Event Types: Use the correct event types for event handlers (e.g.,
React.FormEvent
,React.ChangeEvent
).
Tips
- Use TypeScript's Type Inference: TypeScript can often infer types, reducing the need for explicit type annotations.
- Leverage TypeScript's Utility Types: Use utility types like
Partial
,Pick
, andOmit
to manipulate types. - 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.
TypeScript Course
Module 1: Introduction to TypeScript
- What is TypeScript?
- Setting Up the TypeScript Environment
- Basic Types
- Type Annotations
- Compiling TypeScript
Module 2: Working with Types
Module 3: Advanced Types
Module 4: Functions and Modules
Module 5: Asynchronous Programming
Module 6: Tooling and Best Practices
- Linting and Formatting
- Testing TypeScript Code
- TypeScript with Webpack
- TypeScript with React
- Best Practices