TypeScript与React #
一、React组件类型 #
1.1 函数组件 #
typescript
import React from 'react';
interface ButtonProps {
text: string;
onClick: () => void;
}
const Button: React.FC<ButtonProps> = ({ text, onClick }) => {
return <button onClick={onClick}>{text}</button>;
};
const Button = ({ text, onClick }: ButtonProps) => {
return <button onClick={onClick}>{text}</button>;
};
1.2 类组件 #
typescript
import React from 'react';
interface CounterProps {
initialValue?: number;
}
interface CounterState {
count: number;
}
class Counter extends React.Component<CounterProps, CounterState> {
state: CounterState = {
count: this.props.initialValue ?? 0
};
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<span>{this.state.count}</span>
<button onClick={this.increment}>+</button>
</div>
);
}
}
二、Props类型 #
2.1 基本Props #
typescript
interface UserCardProps {
name: string;
age: number;
email?: string;
onClick?: () => void;
}
const UserCard = ({ name, age, email, onClick }: UserCardProps) => {
return (
<div onClick={onClick}>
<h2>{name}</h2>
<p>Age: {age}</p>
{email && <p>Email: {email}</p>}
</div>
);
};
2.2 子元素类型 #
typescript
interface ContainerProps {
children: React.ReactNode;
}
const Container = ({ children }: ContainerProps) => {
return <div className="container">{children}</div>;
};
interface LayoutProps {
header: React.ReactNode;
children: React.ReactNode;
footer?: React.ReactNode;
}
const Layout = ({ header, children, footer }: LayoutProps) => {
return (
<div>
<header>{header}</header>
<main>{children}</main>
{footer && <footer>{footer}</footer>}
</div>
);
};
2.3 事件处理类型 #
typescript
interface FormProps {
onSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
}
const Form = ({ onSubmit, onChange, onClick }: FormProps) => {
return (
<form onSubmit={onSubmit}>
<input onChange={onChange} />
<button onClick={onClick}>Submit</button>
</form>
);
};
2.4 样式类型 #
typescript
interface StyledButtonProps {
style?: React.CSSProperties;
className?: string;
}
const StyledButton = ({ style, className }: StyledButtonProps) => {
return (
<button style={style} className={className}>
Click me
</button>
);
};
三、Hooks类型 #
3.1 useState #
typescript
const [count, setCount] = useState<number>(0);
const [user, setUser] = useState<User | null>(null);
const [items, setItems] = useState<string[]>([]);
3.2 useEffect #
typescript
useEffect(() => {
console.log('Component mounted');
return () => {
console.log('Component unmounted');
};
}, []);
useEffect(() => {
console.log('Count changed:', count);
}, [count]);
3.3 useRef #
typescript
const inputRef = useRef<HTMLInputElement>(null);
const focusInput = () => {
inputRef.current?.focus();
};
return <input ref={inputRef} />;
3.4 useContext #
typescript
interface ThemeContextType {
theme: 'light' | 'dark';
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within ThemeProvider');
}
return context;
};
3.5 useReducer #
typescript
type State = {
count: number;
};
type Action =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'reset'; payload: number };
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: action.payload };
}
};
const [state, dispatch] = useReducer(reducer, { count: 0 });
3.6 自定义Hook #
typescript
function useFetch<T>(url: string): {
data: T | null;
loading: boolean;
error: Error | null;
} {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
四、事件处理 #
4.1 事件类型 #
typescript
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
console.log(event.currentTarget.value);
};
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
console.log(event.target.value);
};
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
};
4.2 泛型事件处理 #
typescript
function handleEvent<T extends HTMLElement>(
event: React.MouseEvent<T>
): void {
console.log(event.currentTarget);
}
五、实用示例 #
5.1 API组件 #
typescript
interface UserListProps {
users: User[];
onSelect: (user: User) => void;
}
const UserList = ({ users, onSelect }: UserListProps) => {
return (
<ul>
{users.map(user => (
<li key={user.id} onClick={() => onSelect(user)}>
{user.name}
</li>
))}
</ul>
);
};
5.2 表单组件 #
typescript
interface FormData {
username: string;
password: string;
}
const LoginForm = () => {
const [formData, setFormData] = useState<FormData>({
username: '',
password: ''
});
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
console.log(formData);
};
return (
<form onSubmit={handleSubmit}>
<input name="username" onChange={handleChange} />
<input name="password" type="password" onChange={handleChange} />
<button type="submit">Login</button>
</form>
);
};
六、总结 #
本章介绍了TypeScript与React的结合:
组件类型 #
- 函数组件
- 类组件
- Props类型
Hooks类型 #
- useState
- useEffect
- useRef
- useContext
- useReducer
最佳实践 #
- 显式定义Props类型
- 使用类型安全的Hooks
- 正确处理事件类型
最后更新:2026-03-26