React强大且灵活hooks库——ahooks入门实践介绍

简介

ahooks 前端开发的 React Hooks 库,提供了大量实用的自定义 Hooks,帮助开发者快速构建高质量的 React 应用。它遵循 React Hooks 的设计理念,提供了丰富的功能,涵盖了状态管理、网络请求、DOM 操作、工具函数等多个方面。

主要特点

  • 开箱即用:提供 80+ 个实用的 Hooks
  • TypeScript 支持:完整的 TypeScript 类型定义
  • 轻量级:按需引入,支持 Tree Shaking
  • 易学易用:API 设计简洁,学习成本低
  • 社区活跃:持续更新维护,文档完善

安装和配置

安装依赖

复制代码
npm install ahooks

示例

useRequest -- 网络请求管理

复制代码
import { useRequest } from "ahooks";

function UserList() {
  const { data, loading, error } = useRequest(
    async () => {
      const response = await fetch("/api/users");
      return response.json();
    },
    {
      onSuccess: (data) => {
        console.log("请求成功:", data);
      },
      onError: (error) => {
        console.error("请求失败:", error);
      },
    }
  );

  return (
    <div>
      {loading && <div>加载中...</div>}
      {error && <div>错误: {error.message}</div>}
      {data && (
        <ul>
          {data.map((user) => (
            <li key={user.id}>{user.name}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

如果设置了 options.manual = true,则 useRequest 不会默认执行,需要通过 run 来触发执行。

复制代码
const { run } = useRequest(queryData, {
  manual: true,
});

useSetState -- 对象状态管理

复制代码
import { useSetState } from "ahooks";

function UserForm() {
  const [user, setUser] = useSetState({
    name: "",
    email: "",
  });

  const handleChange = (field: string, value: any) => {
    setUser({ [field]: value });
  };

  return (
    <form>
      <input
        value={user.name}
        onChange={(e) => handleChange("name", e.target.value)}
        placeholder="姓名"
      />
      <input
        value={user.email}
        onChange={(e) => handleChange("email", e.target.value)}
        placeholder="邮箱"
      />
    </form>
  );
}

useClickAway -- 点击外部关闭

复制代码
import { useClickAway } from "ahooks";
import { useRef, useState } from "react";

function Dropdown() {
  const [visible, setVisible] = useState(false);
  const ref = useRef();

  useClickAway(() => {
    setVisible(false);
  }, ref);

  return (
    <div ref={ref} style={{ position: "relative" }}>
      <button onClick={() => setVisible(!visible)}>下拉菜单</button>
      {visible && (
        <div
          style={{
            position: "absolute",
            top: "100%",
            border: "1px solid #ccc",
          }}
        >
          <div>菜单项 1</div>
          <div>菜单项 2</div>
          <div>菜单项 3</div>
        </div>
      )}
    </div>
  );
}

useSize -- 监听元素尺寸变化

复制代码
import { useSize } from "ahooks";
import { useRef } from "react";

function ResizableComponent() {
  const ref = useRef();
  const size = useSize(ref);

  return (
    <div ref={ref} style={{ border: "1px solid #ccc", padding: "20px" }}>
      <p>
        当前尺寸: {size?.width} x {size?.height}
      </p>
      <p>调整浏览器窗口大小来查看效果</p>
    </div>
  );
}

useLocalStorageState -- 本地存储状态

复制代码
import { useLocalStorageState } from "ahooks";

function ThemeSwitcher() {
  const [theme, setTheme] = useLocalStorageState("theme", {
    defaultValue: "light",
  });

  return (
    <div>
      <p>当前主题: {theme}</p>
      <button onClick={() => setTheme("light")}>浅色主题</button>
      <button onClick={() => setTheme("dark")}>深色主题</button>
    </div>
  );
}

useDebounceFn -- 防抖函数

复制代码
import { useDebounceFn } from "ahooks";
import { useState } from "react";

function SearchInput() {
  const [searchTerm, setSearchTerm] = useState("");

  const { run: debouncedSearch } = useDebounceFn(
    (value) => {
      console.log("搜索:", value);
      // 执行搜索逻辑
    },
    { wait: 500 } // 500ms 防抖
  );

  const handleChange = (e) => {
    const value = e.target.value;
    setSearchTerm(value);
    debouncedSearch(value);
  };

  return (
    <input value={searchTerm} onChange={handleChange} placeholder="搜索..." />
  );
}

综合示例 -- TodoList

让我们通过一个完整的待办事项应用来实践 ahooks 的使用:

复制代码
import React from "react";
import { useLocalStorageState } from "ahooks";

function TodoList() {
  // 使用本地存储保存待办事项
  const [todos, setTodos] = useLocalStorageState("todos", {
    defaultValue: [],
  });

  const [inputValue, setInputValue] = React.useState("");

  // 添加待办事项
  const addTodo = () => {
    if (!inputValue.trim()) return;

    const newTodo = {
      id: Date.now(),
      text: inputValue.trim(),
      completed: false,
    };

    setTodos([...todos, newTodo]);
    setInputValue("");
  };

  // 切换完成状态
  const toggleTodo = (id) => {
    setTodos(
      todos.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  };

  // 删除待办事项
  const deleteTodo = (id) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  };

  // 处理回车键
  const handleKeyPress = (e) => {
    if (e.key === "Enter") {
      addTodo();
    }
  };

  return (
    <div className="min-h-screen bg-gray-50 py-8 px-4">
      <div className="max-w-md mx-auto">
        <h1 className="text-2xl font-bold text-center text-gray-800 mb-6">
          Todo List
        </h1>

        {/* 添加待办事项 */}
        <div className="bg-white rounded-lg shadow-sm p-4 mb-4">
          <div className="flex gap-2">
            <input
              value={inputValue}
              onChange={(e) => setInputValue(e.target.value)}
              onKeyPress={handleKeyPress}
              placeholder="添加新的待办事项..."
              className="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
            />
            <button
              onClick={addTodo}
              disabled={!inputValue.trim()}
              className="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
            >
              添加
            </button>
          </div>
        </div>

        {/* 待办事项列表 */}
        <div className="space-y-2">
          {todos.length === 0 ? (
            <div className="bg-white rounded-lg shadow-sm p-8 text-center">
              <p className="text-gray-500">还没有待办事项</p>
            </div>
          ) : (
            todos.map((todo) => (
              <div
                key={todo.id}
                className="bg-white rounded-lg shadow-sm p-4 flex items-center gap-3"
              >
                <input
                  type="checkbox"
                  checked={todo.completed}
                  onChange={() => toggleTodo(todo.id)}
                  className="w-4 h-4 text-blue-500 rounded focus:ring-blue-500"
                />
                <span
                  className={`flex-1 ${
                    todo.completed
                      ? "line-through text-gray-400"
                      : "text-gray-800"
                  }`}
                >
                  {todo.text}
                </span>
                <button
                  onClick={() => deleteTodo(todo.id)}
                  className="text-red-500 hover:text-red-700 transition-colors text-sm"
                >
                  删除
                </button>
              </div>
            ))
          )}
        </div>

        {/* 统计信息 */}
        {todos.length > 0 && (
          <div className="bg-white rounded-lg shadow-sm p-4 mt-4">
            <div className="text-sm text-gray-600 flex justify-between items-center">
              <span>总计: {todos.length} 项</span>
              <span>已完成: {todos.filter((t) => t.completed).length} 项</span>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

export default TodoList;

常用 Hooks 速查表

Hook 用途 示例
useRequest 网络请求管理 数据获取、提交表单
useSetState 对象状态管理 表单状态、复杂状态
useLocalStorageState 本地存储状态 用户偏好、缓存数据
useSessionStorageState 会话存储状态 临时数据
useClickAway 点击外部关闭 下拉菜单、模态框
useSize 监听元素尺寸 响应式布局
useDebounceFn 防抖函数 搜索输入、窗口调整
useThrottleFn 节流函数 滚动事件、按钮点击
useInterval 定时器 轮询、倒计时
useTimeout 延时执行 延迟操作
usePrevious 获取前一个值 比较变化
useUpdateEffect 更新时执行 依赖变化时执行
useBoolean 布尔状态管理 开关状态
useCounter 计数器状态 分页、数量控制

总结

ahooks 是一个功能强大且易用的 React Hooks 库,通过本文的介绍和实践,您应该能够:

  1. 理解 ahooks 的核心概念和设计理念
  2. 掌握常用 Hooks 的使用方法
  3. 在实际项目中正确使用 ahooks
  4. 遵循最佳实践,提高代码质量

React强大且灵活hooks库------ahooks入门实践介绍 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿动态资讯

相关推荐
usdoc文档预览2 小时前
USDOC系列之PPT文件在线编辑-VUE前端实现在线浏览器在线编辑PPT文档
前端·vue.js·编辑器·office365·ppt在线编辑·office文件在线编辑·文件在线编辑
用户2705077725242 小时前
Agent 调工具卡住?3 种超时与取消策略实测对比
前端
LuHang3 小时前
我一行代码没写,把领导派的活做成了公司内部系统😭
前端
明月_清风3 小时前
Meta 开源了一个 AI Native 组件库:Astryx,150+ React 组件,专为 AI Agent 而设计
前端·人工智能·ai编程
用户850869276153 小时前
秒杀系统中 Shell 脚本并发控制 Bug:究竟哪里出了
前端
炫酷的大高个6 小时前
6 亿播放的闪身步,我用前端算出 15 倍重心差
前端·javascript
不可能片场6 小时前
内容运营自动化 配图折行别把词切两半
前端·electron
Lank_M6 小时前
HEIC转JPG统一转sRGB,P3高饱和色就回不来了
前端
补码缩写6 小时前
sharp默认转JPG颜色没错,ICC和EXIF却全没了
前端
用户7783366132116 小时前
SerpBase AI Overview 引用卡片:React 组件实战
前端