从写组件到写逻辑:React 自定义 Hooks 的正确打开方式

61 阅读4分钟

写在前面

在 React 开发中,真正拉开水平差距的,往往不是对语法的熟悉程度,而是如何组织和复用逻辑。而自定义 Hooks,正是函数式组件时代实现逻辑抽象与复用的核心利器。

它让我们能够把状态管理、副作用处理、数据获取等通用逻辑从组件中剥离出来,封装成可测试、可共享、高内聚的单元。这不仅提升了代码的可维护性,也让组件本身变得更“纯粹”——只关注 UI 渲染,不掺杂业务细节。

接下来,我们先从 React 内置 Hooks 的核心价值说起。

1. React 自定义 Hooks 概述

1.1 Hooks 是什么?为什么它改变了 React?

Hooks 是 React 16.8 引入的一套新 API,它让函数式组件也能拥有状态(state)、生命周期行为(如挂载/更新/卸载)以及上下文访问能力——这些过去只有类组件才能做到的事情。

更重要的是,Hooks 打破了逻辑复用的壁垒。在类组件时代,我们常被迫使用高阶组件(HOC)或 render props 来共享逻辑,但它们往往带来嵌套地狱、命名冲突和调试困难。而 Hooks 以一种扁平、直观的方式解决了这个问题。

React 提供了几个基础 Hooks,构成了我们日常开发的基石:

  • useState:在函数组件中声明和更新状态。比如管理表单输入、开关状态等。
  • useEffect:处理副作用,例如发起网络请求、订阅事件、操作 DOM 或清理定时器。它统一了 componentDidMountcomponentDidUpdate 和 componentWillUnmount 的职责。
  • useContext:直接消费 React Context,避免多层 props 透传(prop drilling),让全局状态(如用户信息、主题配置)触手可及。

除此之外,还有:

  • useReducer:适合管理复杂状态逻辑;
  • useCallback / useMemo:优化性能,避免不必要的重渲染;
  • useRef:保存可变值或直接访问 DOM 元素。

而所有这些内置 Hooks,都可以作为“积木”,被组合进我们自己的自定义 Hook 中,从而构建出高度可复用的逻辑模块。

我也写了几篇相关的文章,感兴趣的话欢迎继续阅读:

不再层层传 props:React Context 的正确打开方式

从 useState 到 useEffect:React Hooks 核心机制详解

1.2 自定义 Hooks:把逻辑变成可复用的积木

如果说 React 内置的 Hooks(如 useStateuseEffect)是基础工具,

那么自定义 Hooks 就是你亲手打造的专用工具箱

它的核心价值不是复用 UI,而是复用状态逻辑

按照约定,所有自定义 Hook 都以 use 开头(比如 useLocalStorageuseDebounce),这不仅是命名规范,更是向 React 和其他开发者明确传达:“这是一个 Hook,遵循 Hooks 的规则”。

你可以用它封装任何跨组件的通用行为:数据获取、本地存储同步、窗口事件监听、防抖节流、主题切换……只要涉及状态或副作用,就值得考虑抽象成一个自定义 Hook。

响应式todo管理

假设你的应用需要在多个页面读写 localStorage,并且希望状态能自动同步到 React 状态中。我们可以这样封装:

// hooks/useLocalStorage.js
// 封装响应式todos业务
import {
    useState, 
    useEffect
  } from 'react';
  
  const STORAGE_KEY = 'todos';
  function loadFromStorage() {
    const storedTodos = localStorage.getItem(STORAGE_KEY); // 好维护
    return storedTodos ? JSON.parse(storedTodos) : [];
  }
  export const useTodos = () => {
    // useState 接受函数 计算, 同步
    const [todos, setTodos] = useState(loadFromStorage);
    return {
      todos,
      /* addTodo,
      toggleTodo,
      deleteTodo */
    }
  }

未来,当我们需要在 <TodoList><StatsPanel><QuickAdd> 等多个组件中访问或操作 todos 时,只需调用 const { todos } = useTodos() 即可,状态源唯一、逻辑集中、自动持久化

更重要的是,组件本身不再关心“数据从哪来、怎么存”,只专注于如何渲染。这种关注点分离,正是自定义 Hooks 带来的最大价值。

总结

自定义 Hooks 并不是什么炫技的语法糖,而是 React 函数式编程范式下逻辑抽象与工程化思维的自然延伸。它让我们从“在组件里写逻辑”,转变为“用逻辑驱动组件”,真正实现了 关注点分离高内聚低耦合

通过像 useTodos 这样的封装,我们不仅消除了重复代码,还让状态管理更可靠、副作用更可控、测试更简单。更重要的是,组件回归了它的本职——描述 UI,而不再被业务细节所污染。

当你开始习惯把通用逻辑抽离成一个个以 use 开头的小函数时,你会发现:React 应用的结构变得更清晰,协作变得更顺畅,而你自己,也正在从“会用 React”走向“精通 React”。

而这,就是自定义 Hooks 带给我们的,真正的技术红利。