返回首页'%2F%3E%3Ctext%20x%3D'50%25'%20y%3D'50%25'%20dy%3D'.35em'%20text-anchor%3D'middle'%20font-family%3D'sans-serif'%20font-size%3D'34'%20fill%3D'%23ffffff'%3E%E5%B0%8F%3C%2Ftext%3E%3C%2Fsvg%3E)
深入理解 React Hooks:从原理到实践
Hooks 是什么
Hooks 是 React 16.8 引入的特性,允许我们在函数组件中使用状态和生命周期等能力。在此之前,这些功能只有 Class 组件才具备。
Hooks 的核心思想:将组件逻辑拆分为可复用的独立单元。
核心 Hooks
useState:状态管理
const [count, setCount] = useState(0);
useState 返回一个状态值和更新函数。更新时可以直接传新值,也可以传函数:
// 函数式更新,推荐在依赖前一个状态时使用
setCount((prev) => prev + 1);
useEffect:副作用处理
useEffect(() => {
document.title = `点击了 ${count} 次`;
return () => {
// 清理函数
};
}, [count]);
依赖数组的三个场景:
| 依赖数组 | 行为 |
|---------|------|
| [] | 仅在挂载时执行一次 |
| [dep] | dep 变化时执行 |
| 不传 | 每次渲染都执行 |
useRef:持久化引用
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
useRef 适合存储不触发重新渲染的可变值,如 DOM 引用、定时器 ID 等。
useMemo 与 useCallback:性能优化
const sortedList = useMemo(() => {
return list.sort((a, b) => a - b);
}, [list]);
const handleClick = useCallback(() => {
console.log("clicked");
}, []);
注意:不要滥用这两个 Hook。只有当计算确实昂贵、或子组件因引用变化而频繁重渲染时才需要。
自定义 Hooks
自定义 Hooks 是逻辑复用的最佳方式:
function useDebounce<T>(value: T, delay: number): T {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debounced;
}
// 使用
const debouncedSearch = useDebounce(searchTerm, 300);
Hooks 规则
- 只在顶层调用 — 不要在循环、条件或嵌套函数中调用 Hooks
- 只在 React 函数中调用 — 函数组件或自定义 Hook 中
常见陷阱
依赖遗漏
// ❌ 错误:缺少 count 依赖
useEffect(() => {
console.log(count);
}, []);
// ✅ 正确
useEffect(() => {
console.log(count);
}, [count]);
状态更新是异步的
// 连续调用不会累加
setCount(count + 1);
setCount(count + 1);
// 结果只增加 1
// 应该用函数式更新
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
// 结果增加 2
总结
Hooks 让 React 的函数式编程更加纯粹。理解每个 Hook 的设计意图、正确管理依赖、善用自定义 Hooks 抽象逻辑——这些是写出高质量 React 代码的关键。
记住:Hooks 不是银弹,它只是工具。真正的目标是写出清晰、可维护的组件逻辑。
小楼春雨
@站长