React Hooks 详解:2026 年图解指南
发布: (2026年3月29日 GMT+8 06:35)
5 分钟阅读
原文: Dev.to
I’m sorry, but I can’t retrieve the article from the link you provided. If you paste the text you’d like translated here, I’ll be happy to translate it into Simplified Chinese while preserving the formatting.
useState
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
setCount(count + 1)}>
Clicked {count} times
);
}何时使用: 组件在渲染之间需要记住的任何内容——表单值、切换状态、计数器。
注意: 状态更新是异步的。
// ❌ This won't work as expected
setCount(count + 1);
setCount(count + 1); // Both use the same `count` value
// ✅ Use the updater function instead
setCount(prev => prev + 1);
setCount(prev => prev + 1); // Now it's +2Source: …
useEffect
import { useEffect, useState } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
// 在 userId 变化的每次渲染后运行
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(setUser);
}, [userId]); // 依赖数组
return {user?.name};
}依赖数组
| 依赖项 | 行为 |
|---|---|
[] | 挂载时运行一次 |
[value] | 当 value 变化时运行 |
| 无 | 每次渲染后都运行(通常是错误的) |
清理
useEffect(() => {
const subscription = subscribe(userId);
return () => {
subscription.unsubscribe(); // 清理!
};
}, [userId]);useContext
import { createContext, useContext, useState } from 'react';
// 1. Create the context
const ThemeContext = createContext('light');
// 2. Provide it at the top
function App() {
const [theme, setTheme] = useState('dark');
return (
);
}
// 3. Use it anywhere in the tree
function Button() {
const { theme } = useContext(ThemeContext);
return Click me;
}useRef
import { useRef } from 'react';
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<>
聚焦
);
}也可用于存储不应触发重新渲染的值:
const renderCount = useRef(0);
renderCount.current += 1; // Doesn't cause re-renderuseMemo
function ProductList({ products, minPrice }) {
// Recalculates only when `products` or `minPrice` change
const filtered = useMemo(() => {
return products.filter(p => p.price >= minPrice);
}, [products, minPrice]);
return (
{filtered.map(p => - {p.name}
)}
);
}何时使用: 仅在您已测量到导致性能问题的真正昂贵的计算时使用。
useCallback
import { useCallback } from 'react';
function Parent({ id }) {
// Without useCallback, a new function is created every render
const handleClick = useCallback(() => {
doSomethingWith(id);
}, [id]);
return ;
}何时使用: 当将回调函数传递给 React.memo‑包装的子组件,以避免不必要的重新渲染。
useReducer
import { useReducer } from 'react';
const initialState = { count: 0, error: null, loading: false };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'decrement':
return { ...state, count: state.count - 1 };
case 'reset':
return initialState;
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
Count: {state.count}
dispatch({ type: 'increment' })}>+
dispatch({ type: 'decrement' })}>-
);
}使用 useState 的替代方案: 当多个状态片段相互关联并一起变化时。
自定义 Hook(可组合性)
// 用于 API 调用的自定义 Hook
function useApi(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetch(url)
.then(r => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
})
.then(data => { setData(data); setLoading(false); })
.catch(err => { setError(err.message); setLoading(false); });
}, [url]);
return { data, loading, error };
}
// 使用自定义 Hook
function UserList() {
const { data, loading, error } = useApi('/api/users');
if (loading) return ;
if (error) return ;
return
{data.map(u => - {u.name}
)}
;
}Hook Overview
| Hook | Purpose |
|---|---|
useState | 本地状态 |
useEffect | 副作用,数据获取 |
useContext | 在不使用 props 的情况下共享状态 |
useRef | DOM 引用,可变值 |
useMemo | 对昂贵的计算进行记忆化 |
useCallback | 稳定的回调引用 |
useReducer | 复杂的状态逻辑 |