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

相关推荐
李明卫杭州2 分钟前
前端实现多标签页通讯
前端·javascript
前端领航者2 分钟前
国际化LTR&RTL布局实战
前端·css
FanetheDivine4 分钟前
解决@ant-design/icons导致的样式异常
react.js·ant design
贝加尔湖Pan4 分钟前
图片预加载和懒加载
前端
在钱塘江7 分钟前
《你不知道的JavaScript-上卷》第二部分-this和对象原型-笔记-6-行为委托
前端·javascript
Point7 分钟前
[ahooks] useControllableValue源码阅读
前端·javascript
独立开阀者_FwtCoder15 分钟前
踩坑无数后,我终于总结出这份最全的 Vue3 组件通信实战指南
前端·javascript·vue.js
天天扭码15 分钟前
很全面的前端面试题——CSS篇(下)
前端·css·面试
然我44 分钟前
react-router-dom 完全指南:从零实现动态路由与嵌套布局
前端·react.js·面试
一_个前端1 小时前
Vite项目中SVG同步转换成Image对象
前端