返回首页
·4 min read·前端框架

深入理解 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 规则

  1. 只在顶层调用 — 不要在循环、条件或嵌套函数中调用 Hooks
  2. 只在 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 不是银弹,它只是工具。真正的目标是写出清晰、可维护的组件逻辑。

小楼春雨

@站长