跳到主要内容

React中的常用类型

在 React 函数组件中使用 TypeScript 时,有若干常用且关键的类型声明,它们帮助你获得完整的类型安全、自动补全和错误检查。

  1. React 项目是通过 @types/react@types/react-dom 类型声明包,来提供类型的。
  2. 这些包 CRA 已帮我们安装好(react-app-env.d.ts),直接用即可。

✅ 1. 函数组件本身的类型

// TS 会自动推断 props 类型和返回值(JSX.Element)
const MyComponent = ({ name, age }: { name: string; age: number }) => {
return <div>Hello, {name}!</div>;
};

✅ 2. Props 类型定义(最核心!)

推荐:使用 interfacetype

interface Props {
title: string;
count?: number; // 可选属性
onClick: () => void; // 必需回调
status: 'loading' | 'idle' | 'success'; // 字面量联合类型
}

const MyComponent = ({ title, count = 0, onClick, status }: Props) => {
return (
<button disabled={status === 'loading'} onClick={onClick}>
{title} ({count})
</button>
);
};

💡 最佳实践

  • 使用 interface(便于扩展)
  • 明确区分可选(?)和必需属性
  • 回调函数使用 () => void(arg: T) => void

✅ 3. 事件处理函数类型

常见事件类型:

import React, { ChangeEvent, MouseEvent, FormEvent } from 'react';

const InputComponent = () => {
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
console.log(e.target.value);
};

const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
};

const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
};

return (
<form onSubmit={handleSubmit}>
<input onChange={handleChange} />
<button onClick={handleClick}>Submit</button>
</form>
);
};

🔑 常用事件类型

  • ChangeEvent<T>:输入框、选择框等值变化
  • MouseEvent<T>:点击、悬停等
  • KeyboardEvent<T>:键盘事件
  • FormEvent<T>:表单提交
  • FocusEvent<T>:聚焦/失焦

✅ 4. Ref 类型

使用 useRef

import { useRef, useEffect } from 'react';

const FocusInput = () => {
// HTMLInputElement 是 input 元素的类型
const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
inputRef.current?.focus(); // 安全调用
}, []);

return <input ref={inputRef} />;
};

自定义组件 Ref(配合 forwardRef):

import { forwardRef, Ref } from 'react';

interface CustomInputProps {
value: string;
onChange: (val: string) => void;
}

// 自定义组件暴露的 ref 类型(通常是 HTML 元素或实例方法)
const CustomInput = forwardRef<HTMLInputElement, CustomInputProps>(
({ value, onChange }, ref) => {
return <input ref={ref} value={value} onChange={e => onChange(e.target.value)} />;
}
);

✅ 5. Context 类型

import { createContext, useContext } from 'react';

interface ThemeContextType {
theme: 'light' | 'dark';
toggleTheme: () => void;
}

const ThemeContext = createContext<ThemeContextType | null>(null);

// 自定义 hook 封装
const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within ThemeProvider');
}
return context;
};

💡 注意:createContext 的初始值类型要与实际 Provider 提供的值一致。


✅ 6. State 类型(useState)

import { useState } from 'react';

const Counter = () => {
// TS 自动推断 count 为 number
const [count, setCount] = useState(0);

// 显式声明复杂状态
interface User {
id: string;
name: string;
}
const [user, setUser] = useState<User | null>(null);
};

技巧:对复杂对象或可能为 null 的状态,显式标注泛型更安全。


✅ 7. 自定义 Hook 类型

// 返回值类型自动推断,也可显式声明
const useLocalStorage = <T>(key: string, initialValue: T): [T, (value: T) => void] => {
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
return initialValue;
}
});

const setValue = (value: T) => {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
};

return [storedValue, setValue];
};

// 使用
const [name, setName] = useLocalStorage<string>('name', 'Alice');

✅ 8. Children 类型(如果需要显式声明)

虽然通常不需要(因为 JSX 自动处理),但如果组件接受 children 且你想显式约束:

interface CardProps {
children: React.ReactNode; // 最通用
// 或更严格:children: string | JSX.Element | (string | JSX.Element)[];
}

const Card = ({ children }: CardProps) => {
return <div className="card">{children}</div>;
};

📌 React.ReactNode 是最常用的 children 类型,它包括:

  • stringnumber
  • JSX.Element
  • nullundefinedboolean(会被忽略)
  • 数组(嵌套)

✅ 总结:React 函数组件常用 TS 类型清单

场景推荐类型
组件 Propsinterface Props { ... }
事件处理ChangeEvent<HTMLInputElement>, MouseEvent<HTMLButtonElement>
RefsuseRef<HTMLInputElement>(null)
StateuseState<number>(0), useState<User | null>(null)
ContextcreateContext<MyContextType | null>(null)
ChildrenReact.ReactNode(通常无需显式声明)
自定义 Hook 返回值显式元组类型 [T, (v: T) => void]