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入门实践介绍 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿动态资讯

相关推荐
掘金安东尼4 分钟前
用 CSS 打造完美的饼图
前端·css
掘金安东尼8 小时前
纯 CSS 实现弹性文字效果
前端·css
牛奶8 小时前
Vue 基础理论 & API 使用
前端·vue.js·面试
牛奶8 小时前
Vue 底层原理 & 新特性
前端·vue.js·面试
anOnion9 小时前
构建无障碍组件之Radio group pattern
前端·html·交互设计
pe7er9 小时前
状态提升:前端开发中的状态管理的设计思想
前端·vue.js·react.js
SoaringHeart10 小时前
Flutter调试组件:打印任意组件尺寸位置信息 NRenderBox
前端·flutter
晚风予星10 小时前
Ant Design Token Lens 迎来了全面升级!支持在 .tsx 或 .ts 文件中直接使用 Design Token
前端·react.js·visual studio code
sunny_10 小时前
⚡️ vite-plugin-oxc:从 Babel 到 Oxc,我为 Vite 写了一个高性能编译插件
前端·webpack·架构
GIS之路11 小时前
ArcPy 开发环境搭建
前端