TypeScript provides complete type support for React development, improving code reliability.
Using TypeScript allows React components, Props, State, etc. to have complete type checking, reducing runtime errors.
> React Tutorial: [
* * *
* * *
## Why Use TypeScript in React
React component-based development generates large amounts of data flow such as Props, State, and Context.
Without type definitions, it's difficult to track the source and structure of data, prone to runtime errors.
TypeScript provides a complete type system for React: component Props have type checking, useState has type inference, and event handling has type hints.
> **Data Flow:** Data flow in React (Props, State, Context) all require type definitions. TypeScript can ensure type safety for data flow.
* * *
## Creating a Project
Create a React project with TypeScript support using modern scaffolding.
## Initialization
# Using Create React App (slower but complete)
npx create-react-app my-app --template typescript
# Or use Vite (recommended, faster)
npm create vite@latest my-app ----template react-ts
> **Recommendation:** Vite is the most recommended React build tool currently, with fast speed and good development experience.
* * *
## Component Type
Use React.FC type to define function components.
## src/components/Button.tsx
import React from "react";
// Define Props type for Button component
interface ButtonProps {
text: string;// Button text (required)
onClick:()=>void;// Click callback (required)
disabled?:boolean;// Disabled (optional, defaults to false)
variant?:"primary"|"secondary";// Button variant (optional)
}
// Using React.FC Define function component type
const Button: React.FC=({
text,
onClick,
disabled =false,
variant ="primary"
})=>{
return(
);
};
export default Button;
**Result:**
Button component rendered successfully
> **React.FC:** This is the type for React function components, including built-in types like children and propTypes.
* * *
## Props Type
Define the component's Props interface to pass data to child components.
## src/components/UserCard.tsx
import React from "react";
// Define User type
interface User {
id: number;// User ID
name: string;// Username
email: string;// Email
avatar?: string;// Avatar (optional)
}
// Define Props for UserCard component
interface UserCardProps {
user: User;// UserObject (required)
onEdit:(user: User)=>void;// EditCallback
onDelete:(id: number)=>void;// DeleteCallback
}
const UserCard: React.FC=({ user, onEdit, onDelete })=>{
return(
{user.avatar&&}
{user.name}
{user.email}
);
};
export default UserCard;
> **Type Passing:** Pass types through Props to ensure consistent data types throughout the component tree.
* * *
## useState Type
Provide type parameters for useState to ensure correct state types.
## src/components/Counter.tsx
import React,{ useState } from "react";
const Counter: React.FC=()=>{
// Primitive type: explicitly specify number type
const[count, setCount]= useState(0);
// Object type: specify object type
const[user, setUser]= useState({
name:"Alice",
age:25
});
return(
Count:{count}
User:{user.name},{user.age}
);
};
export default Counter;
**Result:**
Counter component rendered successfully
> **Generic Parameter:** The T in useState is the type of the state. If an initial value is provided, TypeScript can infer it automatically.
* * *
## useEffect Type
useEffect also has complete type support.
## src/components/DataFetcher.tsx
import React,{ useState, useEffect } from "react";
// Define User type
interface User {
id: number;
name: string;
}
const DataFetcher: React.FC=()=>{
// UserList State
const[users, setUsers]= useState([]);
// Loading State
const[loading, setLoading]= useState(true);
// ErrorsState
const[error, setError]= useState(null);
useEffect(()=>{
// Mock data fetching
fetch("/api/users")
.then(res => res.json())
.then(data =>{
setUsers(data);
setLoading(false);
})
.catch(err =>{
setError(err.message);
setLoading(false);
});
},[]);// Empty dependency array: executes only once on component mount
if(loading)return
Loading...
;
if(error)return
Errors:{error}
;
return(
{users.map(user =>(
{user.name}
))}
);
};
export default DataFetcher;
> **Dependency Array:** The second parameter of useEffect is the dependency array. TypeScript will check if all variables used in the callback are declared in the array.
* * *
## Event Handling
React events have dedicated type definitions.
## src/components/Form.tsx
import React,{ useState } from "react";
const Form: React.FC=()=>{
// String-typed State
const[name, setName]= useState("");
// Form submit event handler
const handleSubmit =(e: React.FormEvent)=>{
e.preventDefault();// Prevent default form submission
console.log("submit:", name);
};
// Input change event handler
const handleChange =(e: React.ChangeEvent)=>{
setName(e.target.value);
};
return(
);
};
export default Form;
**Result:**
Form component rendered successfully
> **Event Type:** React provides types for each DOM event, such as FormEvent, ChangeEvent, MouseEvent, etc.
* * *
## Notes
* **React.FC:** Recommended to use, provides complete type support
* **Props Interface:** Define Props type for each component
* **useState Generic:** Complex types need explicit specification
* **Event Type:** Use React's event types
> **Best Practice:** Keep type definitions in the same file as the component, or centrally manage them in a types directory.
* * *
## Summary
TypeScript significantly improves the React development experience.
* **React.FC:** Standard type for React function components
* **Props:** Use interface to define component properties
* **useState:** Use generic parameters to specify state types
* **useEffect:** Complete type support
* **Events:** Use React event types to avoid any
> **Recommendation:** Use TypeScript directly