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

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

一、什么是自定义 Hooks?

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

二、案例解析:自定义 Hooks 的实现与使用
1. 案例 1:useMouse------ 封装鼠标位置监听逻辑

功能:实时获取鼠标在页面上的坐标,并在组件卸载时自动清除事件监听,避免内存泄漏。

(1)useMouse的实现(useMouse.js
javascript 复制代码
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组件)

javascript 复制代码
function MouseMove() {
  // 直接调用自定义Hooks,获取鼠标坐标
  const { x, y } = useMouse();
  
  return(
    <div>
      鼠标位置: {x} {y} {/* 只专注于UI渲染,无需关心事件逻辑 */}
    </div>
  )
}
(3)逻辑解析
  • 复用性 :如果其他组件也需要获取鼠标位置,直接调用useMouse()即可,无需重复编写事件绑定 / 清除逻辑。
  • 关注点分离 :组件(MouseMove)只负责渲染 UI,鼠标监听的业务逻辑被封装在useMouse中,代码结构更清晰。
  • 避免内存泄漏 :通过useEffect的返回函数清除事件监听,确保组件卸载后不再执行无用逻辑。
2. 案例 2:useTodos------ 封装待办事项管理逻辑

功能 :管理待办事项的增、删、改状态,并自动同步到localStorage(刷新页面后数据不丢失)。

(1)useTodos的实现(useTodos.js
javascript 复制代码
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

javascript 复制代码
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 中提升代码复用性和可维护性的重要手段,尤其在中大型应用中能显著减少重复代码,让逻辑更清晰。

相关推荐
Easonmax8 小时前
零基础入门 React Native 鸿蒙跨平台开发:7——双向滚动表格实现
react native·react.js·harmonyos
Easonmax8 小时前
零基础入门 React Native 鸿蒙跨平台开发:6——竖向滚动表格实现
react native·react.js·harmonyos
提笔了无痕8 小时前
Web中Token验证如何实现(go语言)
前端·go·json·restful
戌中横8 小时前
JavaScript——Web APIs DOM
前端·javascript·html
Beginner x_u8 小时前
如何解释JavaScript 中 this 的值?
开发语言·前端·javascript·this 指针
HWL56799 小时前
获取网页首屏加载时间
前端·javascript·vue.js
烟锁池塘柳09 小时前
【已解决】Google Chrome 浏览器报错 STATUS_ACCESS_VIOLATION 的解决方案
前端·chrome
速易达网络9 小时前
基于RuoYi-Vue 框架美妆系统
前端·javascript·vue.js
LYS_06189 小时前
RM赛事C型板九轴IMU解算(4)(卡尔曼滤波)
c语言·开发语言·前端·卡尔曼滤波
Easonmax10 小时前
零基础入门 React Native 鸿蒙跨平台开发:8——固定表头和列的复杂表格
react native·react.js·harmonyos