自定义 Hooks 实战(下)

引言

在 React 开发中,自定义 Hooks 是提取组件逻辑、实现代码复用的强大工具。上篇文章我们介绍了自定义 Hooks 的基本概念,今天我们将深入三个实用的自定义 Hooks:useFetch、useDebounce和useInterval,看看它们如何解决实际开发中的常见问题。


1. useFetch - 优雅的数据获取

使用场景

处理 API 请求时,我们需要管理加载状态、错误处理和响应数据。useFetch 将这些逻辑封装成一个可复用的 Hook。

完整实现

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

function useFetch<T>(url: string) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err as Error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

使用示例

javascript 复制代码
function UserProfile({ userId }: { userId: string }) {
  const { data, loading, error } = useFetch<User>(
    `/api/users/${userId}`
  );

  if (loading) return <div>加载中...</div>;
  if (error) return <div>错误:{error.message}</div>;
  if (!data) return null;

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.email}</p>
    </div>
  );
}

2. useDebounce - 防抖优化

使用场景

在搜索框输入、窗口大小调整等高频触发场景中,useDebounce 可以延迟执行,避免不必要的计算和请求。

完整实现

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

function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value);

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [value, delay]);

  return debouncedValue;
}

使用示例

ini 复制代码
function SearchBox() {
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearchTerm = useDebounce(searchTerm, 500);

  useEffect(() => {
    // 只在用户停止输入 500ms 后执行搜索
    if (debouncedSearchTerm) {
      fetchSearchResults(debouncedSearchTerm);
    }
  }, [debouncedSearchTerm]);

  return (
    <input
      type="text"
      value={searchTerm}
      onChange={(e) => setSearchTerm(e.target.value)}
      placeholder="搜索..."
    />
  );
}

3. useInterval - 定时器 Hook

使用场景

需要周期性执行某些操作(如轮询、动画、倒计时)时,useInterval 提供了声明式的定时器管理。

完整实现

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

function useInterval(callback: () => void, delay: number | null) {
  const savedCallback = useRef<() => void>();

  // 记住最新的回调函数
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // 设置定时器
  useEffect(() => {
    function tick() {
      savedCallback.current?.();
    }

    if (delay !== null) {
      const id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

使用示例

scss 复制代码
function Counter() {
  const [count, setCount] = useState(0);

  useInterval(() => {
    setCount(count + 1);
  }, 1000);

  return <div>计数:{count}</div>;
}

总结对比

Hook 核心用途 关键特性 典型场景
useFetch 数据获取 自动管理 loading/error/state API 调用、数据加载
useDebounce 防抖优化 延迟值更新、自动清理定时器 搜索框、输入验证
useInterval 定时执行 支持动态延迟、自动清理 轮询、动画、倒计时

最佳实践建议

  1. 命名规范 :自定义 Hook 必须以 use 开头
  2. 依赖管理 :确保 useEffect 依赖数组完整
  3. 清理副作用:返回清理函数避免内存泄漏
  4. 类型安全:使用 TypeScript 泛型提高类型推断
  5. 测试覆盖:为自定义 Hook 编写单元测试
相关推荐
晓得迷路了1 小时前
栗子前端技术周刊第 149 期 - Vite+ 1.0、Preact 11、Next.js 16.4...
前端·javascript·react.js
song5011 小时前
React Native for OpenHarmony 实战:三方库 react-native-popup-menu 的鸿蒙化适配指南
css·深度学习·react native·react.js·transformer·harmonyos
haluhalu.2 小时前
Agent = LLM + 上下文 + 工具(含观察 / 动作空间、ReAct 循环)
前端·javascript·人工智能·python·react.js·机器学习·个人开发
weixin_4481199411 小时前
Datawhale Easy Data × AI:构建知识与记忆驱动的 Agent笔记8
人工智能·笔记·react.js
EatFan14 小时前
React 项目踩坑实录:useEffect 闭包陷阱、Context 性能陷阱与 React 18 升级避坑排查手册
前端·javascript·react.js·react·react hooks·useeffect·闭包陷阱
梦想的颜色19 小时前
【编程实战】AI 时代 APP 开发全栈硬核指南:技术选型 + AI 架构 + 模型落地全维度决策
python·flutter·react native·react.js·ai·桌面应用·milvus
知野小兔19 小时前
对比react钩子函数
react.js
阿狗童鞋2 天前
React实战指南
前端·react.js·前端框架
用户298698530142 天前
React 中实现 Word 与 Markdown 双向转换的实践记录
javascript·react.js·markdown