掌握 React Hooks 高级用法:useCallback、useMemo、useReducer、自定义 Hooks 和性能优化模式。React 开发者完整指南。
# React Hooks 高级使用指南
学习掌握 React Hooks 高级用法,构建高效且可维护的应用程序。
## 基础 Hooks 与 TypeScript
### useState 类型定义
```typescript
import { useState } from "react";
interface User {
id: number;
name: string;
email: string;
isActive: boolean;
}
function UserProfile() {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [errors, setErrors] = useState<string[]>([]);
const updateName = (newName: string) => {
setUser((prev) =>
prev ? { ...prev, name: newName } : null
);
};
return (
<div>
{loading ? (
<p>加载中...</p>
) : user ? (
<h1>欢迎,{user.name}</h1>
) : (
<p>用户未找到</p>
)}
</div>
);
}
```
## useReducer 处理复杂状态
```typescript
interface Product {
id: string;
name: string;
price: number;
quantity: number;
}
interface CartState {
items: Product[];
total: number;
itemCount: number;
}
type CartAction =
| { type: "ADD_ITEM"; payload: Product }
| { type: "REMOVE_ITEM"; payload: string }
| { type: "UPDATE_QUANTITY"; payload: { id: string; quantity: number } }
| { type: "CLEAR_CART" };
function cartReducer(state: CartState, action: CartAction): CartState {
switch (action.type) {
case "ADD_ITEM": {
const existing = state.items.find((p) => p.id === action.payload.id);
if (existing) {
const updatedItems = state.items.map((p) =>
p.id === action.payload.id
? { ...p, quantity: p.quantity + 1 }
: p
);
return calculateTotals({ ...state, items: updatedItems });
}
return calculateTotals({
...state,
items: [...state.items, { ...action.payload, quantity: 1 }],
});
}
case "REMOVE_ITEM": {
const filteredItems = state.items.filter((p) => p.id !== action.payload);
return calculateTotals({ ...state, items: filteredItems });
}
case "CLEAR_CART":
return { items: [], total: 0, itemCount: 0 };
default:
return state;
}
}
function calculateTotals(state: CartState): CartState {
const total = state.items.reduce((sum, p) => sum + p.price * p.quantity, 0);
const itemCount = state.items.reduce((sum, p) => sum + p.quantity, 0);
return { ...state, total, itemCount };
}
```
## 自定义 Hooks
### useLocalStorage
```typescript
import { useState, useEffect } from "react";
export function useLocalStorage<T>(
key: string,
initialValue: T
): [T, (value: T | ((prev: T) => T)) => void] {
const [storedValue, setStoredValue] = useState<T>(() => {
if (typeof window === "undefined") return initialValue;
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error("读取 localStorage 错误:", error);
return initialValue;
}
});
useEffect(() => {
try {
window.localStorage.setItem(key, JSON.stringify(storedValue));
} catch (error) {
console.error("写入 localStorage 错误:", error);
}
}, [key, storedValue]);
return [storedValue, setStoredValue];
}
// 使用示例
function Settings() {
const [theme, setTheme] = useLocalStorage("theme", "light");
const [language, setLanguage] = useLocalStorage("language", "zh");
return (
<div>
<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
当前主题: {theme === "light" ? "浅色" : "深色"}
</button>
</div>
);
}
```
### useFetch 数据获取
```typescript
import { useState, useEffect, useCallback } from "react";
interface FetchState<T> {
data: T | null;
loading: boolean;
error: Error | null;
}
export function useFetch<T>(url: string) {
const [state, setState] = useState<FetchState<T>>({
data: null,
loading: true,
error: null,
});
const fetchData = useCallback(async () => {
setState((prev) => ({ ...prev, loading: true }));
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP 错误: ${response.status}`);
}
const data = await response.json();
setState({ data, loading: false, error: null });
} catch (error) {
setState({ data: null, loading: false, error: error as Error });
}
}, [url]);
useEffect(() => {
fetchData();
}, [fetchData]);
return { ...state, refetch: fetchData };
}
```
## 性能优化
```typescript
import { useMemo, useCallback, memo } from "react";
interface Product {
id: string;
name: string;
price: number;
category: string;
}
export function ProductList({
products,
selectedCategory,
onSelect,
}: {
products: Product[];
selectedCategory: string;
onSelect: (id: string) => void;
}) {
// 记忆化过滤后的产品
const filteredProducts = useMemo(() => {
console.log("过滤产品...");
return products.filter(
(p) => !selectedCategory || p.category === selectedCategory
);
}, [products, selectedCategory]);
// 记忆化点击处理函数
const handleClick = useCallback(
(id: string) => {
onSelect(id);
},
[onSelect]
);
return (
<ul className="grid grid-cols-3 gap-4">
{filteredProducts.map((product) => (
<ProductCard
key={product.id}
product={product}
onClick={handleClick}
/>
))}
</ul>
);
}
// 记忆化组件避免不必要的重新渲染
const ProductCard = memo(function ProductCard({
product,
onClick,
}: {
product: Product;
onClick: (id: string) => void;
}) {
return (
<li
onClick={() => onClick(product.id)}
className="p-4 border rounded-lg cursor-pointer hover:shadow-lg"
>
<h3 className="font-bold">{product.name}</h3>
<p className="text-blue-600">¥{product.price}</p>
</li>
);
});
```
这份 React Hooks 高级指南帮助中文开发者掌握 Hooks 的最佳实践和性能优化技巧。This react prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their react implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For react projects, consider mentioning your framework version, coding style, and any specific libraries you're using.