自定义 Hooks 的用法和意义详解(结合案例)

自定义 Hooks 的用法和意义详解(结合案例)

一、什么是自定义 Hooks?

自定义 Hooks 是 React 中复用状态逻辑 的一种机制,本质是一个以use开头的函数,内部可以调用其他 Hooks(包括内置 Hooks 如useStateuseEffect或其他自定义 Hooks)。它的核心作用是将组件中重复的状态管理、副作用处理等逻辑提取出来,实现逻辑复用,让组件更专注于 UI 渲染。

二、案例解析:自定义 Hooks 的实现与使用

  1. 案例 1:useMouse------ 封装鼠标位置监听逻辑
    功能 :实时获取鼠标在页面上的坐标,并在组件卸载时自动清除事件监听,避免内存泄漏。

(1)useMouse的实现(useMouse.js

复制代码
 import { useState, useEffect } from "react"

// 自定义Hooks必须以use开头
export const useMouse = () => {
  // 1. 用useState保存鼠标坐标状态
  const [x, setX] = useState(0);
  const [y, setY] = useState(0);

  // 2. 用useEffect处理副作用(添加/清除鼠标移动事件)
  useEffect(() => {
    // 定义事件处理函数:更新鼠标坐标
    const update = (event) => {
      setX(event.pageX); // 更新x坐标
      setY(event.pageY); // 更新y坐标
    };

    // 绑定鼠标移动事件
    window.addEventListener('mousemove', update);

    // 3. 清除副作用:组件卸载时移除事件监听(防止内存泄漏)
    return () => {
      window.removeEventListener('mousemove', update);
    };
  }, []); // 空依赖数组:只在组件挂载时执行一次

  // 4. 返回需要暴露的状态(鼠标坐标)
  return { x, y };
}

(2)useMouse的使用(App.jsx中的MouseMove组件)

复制代码
function MouseMove() {
  // 直接调用自定义Hooks,获取鼠标坐标
  const { x, y } = useMouse();
  
  return(
    <div>
      鼠标位置: {x} {y} {/* 只专注于UI渲染,无需关心事件逻辑 */}
    </div>
  )
}

(3)逻辑解析

  • 复用性 :如果其他组件也需要获取鼠标位置,直接调用useMouse()即可,无需重复编写事件绑定 / 清除逻辑。
  • 关注点分离 :组件(MouseMove)只负责渲染 UI,鼠标监听的业务逻辑被封装在useMouse中,代码结构更清晰。
  • 避免内存泄漏 :通过useEffect的返回函数清除事件监听,确保组件卸载后不再执行无用逻辑。
  1. 案例 2:useTodos------ 封装待办事项管理逻辑
    功能 :管理待办事项的增、删、改状态,并自动同步到localStorage(刷新页面后数据不丢失)。

(1)useTodos的实现(useTodos.js

复制代码
import { useState, useEffect } from 'react';

const STORAGE_KEY = 'todos'; // 本地存储的key(便于维护)

// 从localStorage加载待办事项
function loadFromStorage() {
  const storedTodos = localStorage.getItem(STORAGE_KEY);
  return storedTodos ? JSON.parse(storedTodos) : [];
}

// 保存待办事项到localStorage
function saveToStorage(todos) {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
}

export const useTodos = () => {
  // 1. 用useState初始化待办事项(从本地存储加载)
  const [todos, setTodos] = useState(loadFromStorage);

  // 2. 用useEffect同步数据到localStorage(todos变化时触发)
  useEffect(() => {
    saveToStorage(todos);
  }, [todos]); // 依赖todos:只有todos变化时才执行

  // 3. 定义添加待办事项的方法
  const addTodo = (text) => {
    setTodos([
      ...todos,
      { id: Date.now(), text, completed: false } // 生成新的待办项
    ]);
  };

  // 4. 定义切换待办事项完成状态的方法
  const toggleTodo = (id) => {
    setTodos(todos.map(todo => 
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  // 5. 定义删除待办事项的方法
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  // 6. 返回状态和方法(供组件使用)
  return { todos, addTodo, toggleTodo, deleteTodo };
}

(2)useTodos的使用(App.jsx

复制代码
import { useTodos } from './hooks/useTodos.js';
import TodoList from './components/TodoList.jsx';
import TodoInput from './components/TodoInput.jsx';

export default function App() {
  // 调用自定义Hooks,获取待办事项的状态和操作方法
  const { todos, addTodo, toggleTodo, deleteTodo } = useTodos();

  return(
    <>
      {/* 传入addTodo方法给输入组件 */}
      <TodoInput addTodo={addTodo}/>
      {/* 根据todos状态渲染列表或提示文本 */}
      {
        todos.length > 0 ? (
          <TodoList 
            onDelete={deleteTodo}
            onToggle={toggleTodo}
            todos={todos}
          />
        ) : (
          <div>暂无待办事项</div>
        )
      }
    </>
  )
}

(3)逻辑解析

  • 状态复用 :待办事项的加载、保存、增删改逻辑被完全封装,任何需要待办功能的组件都可以通过useTodos复用。
  • 简化组件App组件无需关心localStorage操作、状态更新细节,只需调用方法和渲染 UI,代码量大幅减少。
  • 一致性:所有与待办相关的逻辑集中管理,避免多处重复代码导致的维护问题(如修改存储 key 时只需改一处)。

三、自定义 Hooks 的核心意义

  1. 逻辑复用 解决了类组件中 "混入(mixin)" 带来的命名冲突、依赖混乱等问题,通过函数调用的方式优雅复用状态逻辑(如useMouseuseTodos可在任意组件中重复使用)。
  2. 关注点分离将组件中的 "业务逻辑"(如事件监听、数据存储)与 "UI 渲染" 分离,使组件更简洁,便于阅读和维护(组件只关心渲染,Hooks 只关心逻辑)。
  3. 可测试性 自定义 Hooks 是纯函数,可独立于组件进行单元测试,验证逻辑正确性(如测试useTodosaddTodo方法是否正确添加数据)。
  4. 代码一致性 团队中可通过自定义 Hooks 统一业务逻辑的实现方式(如所有数据持久化都用类似useTodos的模式),降低协作成本。

四、自定义 Hooks 的使用规范

  • 必须以use开头(如useMouseuseTodos),React 通过命名识别 Hooks,确保 Hooks 的规则(如只能在顶层调用)被遵守。
  • 内部可以调用其他 Hooks(内置或自定义),但不能在条件语句、循环中调用(需遵循 React Hooks 的调用规则)。
  • 必须返回组件需要的状态或方法(通常是对象或数组,便于解构使用)。

通过上述案例可以看出,自定义 Hooks 是 React 中提升代码复用性和可维护性的重要手段,尤其在中大型应用中能显著减少重复代码,让逻辑更清晰。

原文: https://juejin.cn/post/75906018

相关推荐
DIKKOO4 小时前
React 19 修复了一个遗留多年的类型乌龙,过程竞如此曲折
前端·react.js
程序员爱钓鱼4 小时前
Node.js 编程实战:Node.js + React Vue Angular 前后端协作实践
前端·后端·node.js
程序员爱钓鱼4 小时前
Node.js 编程实战:前后端结合的 SSR 服务端渲染
前端·后端·node.js
haokan_Jia4 小时前
Java 并发编程-ScheduledFuture
java·前端·python
bst@微胖子4 小时前
CrewAI+FastAPI实现多Agent协作项目
java·前端·fastapi
掘金酱4 小时前
TRAE 2025 年度报告分享活动|获奖名单公示🎊
前端·人工智能·后端
jqq6665 小时前
解析ElementPlus打包源码(三、打包类型)
前端·javascript·vue.js
白哥学前端5 小时前
独立开发实战:我用 AI 写了一个台球小程序
前端·后端·trae
陳陈陳5 小时前
React 性能优化双子星:useMemo 与 useCallback 的正确打开方式
前端·javascript·react.js
持续前行5 小时前
JavaScript 数组中删除偶数下标值的多种方法
前端·javascript·vue.js