欢迎光临
我们一直在努力

React Hook 浅学 2.0 - 自定义Hook

关于 ahooks 插件

ahooks 是一个高质量的 React Hooks 库,由阿里巴巴团队开发和维护。它提供了大量实用的自定义 Hooks,帮助开发者更高效地构建 React 应用。ahooks 的设计理念是"开箱即用",通过封装常见的业务场景逻辑,让开发者能够专注于业务实现,而不是重复造轮子。

版本演进:ahooks 目前已经发展到 v3.x 版本,支持 React 16.8+,并全面拥抱 TypeScript。库的 API 设计遵循 React Hooks 的最佳实践,同时提供了丰富的配置选项和扩展能力。

核心功能

ahooks 提供了丰富的 Hooks 分类,包括状态管理、副作用处理、DOM 操作、生命周期、网络请求、UI 交互等。以下是主要分类:

  • 状态管理:useSetState、useToggle、useBoolean、useMap、useSet 等
  • 副作用处理:useDebounce、useThrottle、useInterval、useTimeout、useUpdateEffect 等
  • DOM 操作:useClickAway、useHover、useScroll、useSize、useFullscreen 等
  • 网络请求:useRequest(核心 Hook,支持轮询、防抖、节流、缓存等)
  • 生命周期:useMount、useUnmount、useUpdate 等
  • 工具函数:useMemoizedFn、useLatest、useCreation 等

常见 Hooks 如 useRequest(异步请求管理)、useScroll(滚动监听)、useSize(元素尺寸监听)等,都经过了大量生产环境的验证。

安装与使用

通过 npm 或 yarn 安装 ahooks:

# 使用 npm
npm install ahooks –save
使用 yarn
yarn add ahooks
使用 pnpm
pnpm add ahooks

按需引入:ahooks 支持 Tree Shaking,建议按需引入以减小打包体积:

import { useRequest, useToggle } from 'ahooks';

在 React 组件中使用示例:

import React from 'react';
import { useRequest, useToggle } from 'ahooks';

function UserList() {
// 使用 useRequest 管理异步请求
const { data, loading, error, run } = useRequest(
() => fetch('/api/users').then(res => res.json()),
{
manual: false, // 是否手动触发
onSuccess: (result) => {
console.log('请求成功:', result);
},
onError: (error) => {
console.error('请求失败:', error);
}
}
);

// 使用 useToggle 管理开关状态
const [isVisible, { toggle, setLeft, setRight }] = useToggle(false);

if (loading) return <div>加载中…</div>;
if (error) return <div>加载失败: {error.message}</div>;

return (
<div>
<h1>用户列表</h1>
<button onClick={toggle}>
{isVisible ? '隐藏列表' : '显示列表'}
</button>

{isVisible && (
<ul>
{data?.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</div>
);
}

export default UserList;

特点与优势

  • 开箱即用:封装了常见场景的 Hooks,减少重复代码。每个 Hook 都经过精心设计,API 简洁直观。
  • 高性能:内置优化逻辑,避免不必要的渲染。例如 useMemoizedFn 可以持久化函数引用,useCreation 可以替代 useMemo 和 useRef。
  • TypeScript 支持:完整的类型定义,提升开发体验。所有 Hook 都有详细的类型提示和文档。
  • 模块化设计:按需引入,减小打包体积。支持 Tree Shaking,只打包用到的代码。
  • 测试友好:所有 Hook 都提供了完善的单元测试,确保稳定性和可靠性。
  • 社区活跃:由阿里巴巴团队维护,定期更新,响应 issue 和 PR 迅速。

适用场景

  • 需要快速实现复杂逻辑的 React 项目:ahooks 提供了大量现成的解决方案,可以显著加快开发速度。
  • 希望减少自定义 Hooks 开发时间的情况:避免重复造轮子,专注于业务逻辑。
  • 团队统一 Hooks 规范,提升代码可维护性:使用统一的 Hooks 库可以保证代码风格一致。
  • 需要处理复杂状态管理的应用:ahooks 的状态管理 Hook 可以简化复杂的状态逻辑。
  • 需要优化性能的应用:内置的性能优化 Hook 可以帮助减少不必要的渲染。

最佳实践

  • 按需引入:只引入需要的 Hook,避免打包体积过大。
  • 理解 Hook 的依赖项:合理设置依赖数组,避免不必要的重新执行。
  • 错误处理:使用 useRequest 的错误处理机制,提供更好的用户体验。
  • 组合使用:多个 Hook 可以组合使用,实现更复杂的功能。
  • 自定义扩展:基于 ahooks 的 Hook 进行二次封装,满足特定业务需求。
  • 资源与社区

    • 官方文档:ahooks.js.org – 包含详细的 API 文档、示例和指南
    • GitHub 仓库:alibaba/hooks – 开源代码,可以提交 issue 和 PR

    常见自定义 Hook 表格

    以下是一些常见的自定义 Hook,整理成表格说明它们的意义和使用方法:

    Hook 名称意义使用方法适用场景
    useToggle 用于切换布尔状态,简化开关逻辑 const [isOn, { toggle, set, setLeft, setRight }] = useToggle(false) 开关、显示/隐藏、模式切换
    useDebounce 对输入值进行防抖处理,避免频繁触发回调 const debouncedValue = useDebounce(value, 500) 搜索框输入、窗口大小调整、滚动事件
    useLocalStorage 将状态同步到 localStorage,实现持久化存储 const [name, setName] = useLocalStorage('name', '') 用户偏好设置、表单数据持久化
    useWindowSize 获取窗口尺寸,响应窗口变化 const { width, height } = useWindowSize() 响应式布局、移动端适配
    useRequest 封装数据请求逻辑,简化异步操作 const { loading, data, error, run } = useFetch(url, options) API 调用、数据获取、表单提交
    usePrevious 保存上一次的状态值,便于比较前后变化 const prevCount = usePrevious(count) 状态变化追踪、动画效果、性能优化
    useClickOutside 检测点击事件是否发生在目标元素外部,常用于关闭弹窗 useClickOutside(() => setIsOpen(false), [isOpen]) 下拉菜单、模态框、弹出层
    useHover 检测鼠标悬停状态 const [isHovered, bind] = useHover() 交互反馈、Tooltip、高亮效果
    useTimeout 封装 setTimeout 逻辑,自动清理定时器 useTimeout(() => alert('Done!'), 1000) 延迟执行、倒计时、轮询
    useScrollPosition 获取滚动位置,监听页面滚动 const scrollY = useScrollPosition() 无限滚动、回到顶部、阅读进度
    useKeyPress 监听键盘按键事件 useKeyPress('Enter', callback) 快捷键、表单提交、游戏控制
    useNetwork 获取网络连接状态 const networkState = useNetwork() 离线提示、网络状态检测
    useTitle 动态修改页面标题 useTitle('新标题') SPA 页面标题管理、通知提醒

    示例代码

    useToggle – 完整示例

    import React from 'react';
    import { useToggle } from 'ahooks';

    function ToggleDemo() {
    const [state, { toggle, set, setLeft, setRight }] = useToggle();

    return (
    <div>
    <p>当前状态: {state.toString()}</p>
    <button onClick={toggle}>切换</button>
    <button onClick={() => set(false)}>设为 false</button>
    <button onClick={() => set(true)}>设为 true</button>
    <button onClick={setLeft}>设为 false (setLeft)</button>
    <button onClick={setRight}>设为 true (setRight)</button>
    </div>
    );
    }

    function ToggleWithInitialValue() {
    const [isDarkMode, toggleDarkMode] = useToggle(true);

    return (
    <div>
    <p>深色模式: {isDarkMode ? '开启' : '关闭'}</p>
    <button onClick={toggleDarkMode}>切换深色模式</button>
    </div>
    );
    }

    useDebounce – 搜索框示例

    import React, { useState, useEffect } from 'react';
    import { useDebounce } from 'ahooks';

    function SearchBox() {
    const [searchTerm, setSearchTerm] = useState('');
    const debouncedSearchTerm = useDebounce(searchTerm, 500);
    const [results, setResults] = useState([]);
    const [loading, setLoading] = useState(false);

    useEffect(() => {
    if (debouncedSearchTerm) {
    setLoading(true);
    setTimeout(() => {
    setResults([
    `结果 1: ${debouncedSearchTerm}`,
    `结果 2: ${debouncedSearchTerm} 相关`,
    `结果 3: ${debouncedSearchTerm} 信息`
    ]);
    setLoading(false);
    }, 300);
    } else {
    setResults([]);
    }
    }, [debouncedSearchTerm]);

    return (
    <div>
    <input
    type="text"
    value={searchTerm}
    onChange={(e) => setSearchTerm(e.target.value)}
    style={{ padding: '8px', width: '300px' }}
    />
    {loading && <div>搜索中…</div>}
    {results.length > 0 ? (
    <ul>
    {results.map((result, index) => (
    <li key={index}>{result}</li>
    ))}
    </ul>
    ) : (
    debouncedSearchTerm && <div>未找到相关结果</div>
    )}
    </div>
    );
    }

    export default SearchBox;

    useLocalStorage – 用户设置示

    import React from 'react';
    import { useLocalStorage } from 'ahooks';

    function UserSettings() {
    // 存储用户偏好
    const [theme, setTheme] = useLocalStorage('theme', 'light');
    const [fontSize, setFontSize] = useLocalStorage('fontSize', 14);
    const [notifications, setNotifications] = useLocalStorage('notifications', true);

    return (
    <div>
    <h2>用户设置</h2>
    <div>
    主题:
    <select
    value={theme}
    onChange={(e) => setTheme(e.target.value)}
    style={{ marginLeft: '10px' }}
    >
    <option value="light">浅色</option>
    <option value="dark">深色</option>
    <option value="auto">自动</option>
    </select>
    </div>
    </div>
    );
    }

    赞(0)
    未经允许不得转载:171主机测评 » React Hook 浅学 2.0 - 自定义Hook
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址