# 解析ahooks整体架构及React工具库源码

> 作者/来源: UCloud 运营管理员
> 发布时间: 2022-11-06T10:34:00.000Z
> 分类: 解决方案
> 原文链接: http://117.50.162.249:3000/yun/articles/2202

---

# 解析ahooks整体架构及React工具库源码

> 来源: https://www.ucloud.cn/yun/128268.html
> 作者: 3403771864
> 发布日期: 发布于2022-11-06 18:34

这是讲 ahooks 源码的第一篇文章，简要就是以下几点：

　　加深对 React hooks 的理解。

　　学习如何抽象自定义 hooks。构建属于自己的 React hooks 工具库。

　　培养阅读学习源码的习惯，工具库是一个对源码阅读不错的选择。

　　注：本系列对 ahooks 的源码解析是基于v3.3.13。自己 folk 了一份源码，主要是对源码做了一些解读，可见详情。

　　第一篇主要介绍 ahooks 的背景以及整体架构。

　　React hooks utils 库

　　自从 React 16.8 版本推出 React hooks，使用 Function Component越来越广泛。React hooks utils 库随即诞生，直接解决下面两个问题：

　　公共逻辑的抽象。

　　解决 React hooks 存在的弊端，比如闭包等。

　　那现在社区有哪些比较优秀的 React Hooks utils 库呢？

　　react-use是社区比较活跃的 React hooks utils 库，它的 star 数达到了29.6k。它的功能非常强大，拥有的 hooks 已经 100+。假如你需要功能比较齐全，可以考虑选择 react-use。

　　有点需要注意的是如果只需要一些常见的功能，react-use就有 可能会稍微冗余了，这时候就可以考虑到——ahooks，目前它的 star 数为9.2k，也算是社区比较活跃。

　　ahooks

　　简介

　　官方介绍如下：

　　ahooks，发音 [eɪ hʊks]，是一套高质量可靠的 React Hooks 库。在当前 React 项目研发过程中，一套好用的 React Hooks 库是必不可少的，希望 ahooks 能成为您的选择。

　　特点

　　它具有如下特点：

　　易学易用。

　　支持 SSR。

　　将访问 DOM/BOM 的方法放在 useEffect 中（服务端不会执行），避免服务端执行时报错。

　　源码中可以看到很多isBrowser的判断，主要是区分开浏览器环境和服务器环境。

　　对输入输出函数做了特殊处理，且避免闭包问题。

　　输入的函数，永远都是使用最新的一份。这个是通过useRef进行实现。

　　输出函数，地址都是不会变化的，这个是通过useMemoizedFn（ahooks 封装的）实现的，其实现也是通过useRef实现。后面我们会提到。

　　包含大量提炼自业务的高级 Hooks。

　　包含丰富的基础 Hooks。

　　使用 TypeScript 构建，提供完整的类型定义文件。可以学习一些 TypeScript 的技巧。

　　hooks 种类

　　ahooks 基于 UI、SideEffect、LifeCycle、State、DOM 等分类提供了常用的 Hooks。如下所示：

![1.png](https://ucloud-blog.cn-bj.ufileos.com/articles/128268/images/128268_000.png)

　　ahooks 整体架构

　　项目启动

　　这是要先做准备，先从 ahooks 中 folk一份，clone 下来。

```
　yarn run init
　　yarn start
```

　　整体结构

　　从仓库的根目录的 package.json 中可以得到以下信息。

　　文档是使用dumi。是一款为组件开发场景而生的文档工具。

　　该项目是一个monoRepo。它的项目管理是通过lerna进行管理的。

　　单元测试是通过 jest 实现。

　　在目录结构中，明显看到docs 中存放仓库公共文档。packages 中存放两个包，hooks 和 use-url-state。整体的结构跟 dumi 中给出的 lerna 项目的结构相似。其中每个包下面的每个组件都可以书写对应的文档，有所不同的是，hooks 中每个组件多了\_\_tests\_\_文件夹，这个是用来写单元测试的。

![2.png](https://ucloud-blog.cn-bj.ufileos.com/articles/128268/images/128268_001.png)

　　可以用以下一张图，大致总结一下 ahooks 的工程架构：

![3.png](https://ucloud-blog.cn-bj.ufileos.com/articles/128268/images/128268_002.png)

　　hooks

　　就我们所知ahooks 是采用了monoRepo的方式，这时候源码中就有 packages ，接下来看看 hooks。先看packages/hooks/package.json。另外要使用 useUrlState 这个 hook，需要独立安装@ahooksjs/use-url-state，其源码在packages/use-url-state中。官方意思就是这个库依赖于 react-router，这样有可能一些项目不需要用到，把它提出来有助于减少包的大小。

```
　　npm i @ahooksjs/use-url-state -S
```

　　回到packages/hooks。重点关注一下 dependencies 和 peerDependencies。可以看到其实它内部还是使用了一些其他的工具库的，比如 lodash（估计是避免重复造轮子，但感觉这样会导致包会变大）。后面我们也会对这些工具库做一个探索。

```
　　"dependencies": {
　　"@types/js-cookie": "^2.x.x",
　　"ahooks-v3-count": "^1.0.0",
　　"dayjs": "^1.9.1",
　　"intersection-observer": "^0.12.0",
　　"js-cookie": "^2.x.x",
　　"lodash": "^4.17.21",
　　"resize-observer-polyfill": "^1.5.1",
　　"screenfull": "^5.0.0"
　　},
　　"peerDependencies": {
　　"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
　　},
```

　　另外解释下 peerDependencies。

　　peerDependencies的目的是就是为了提示宿主环境去安装满足插件peerDependencies所指定依赖的包，之后在插件import或者require所依赖的包的时候，永远都是引用宿主环境统一安装的npm包，最终解决插件与所依赖包不一致的问题。这里要的说的宿主环境其实就是项目本身。

　　这点对于封装 npm 包十分要紧。当你写的包 a 里面依赖另一个包 b，而这个包 b 是引用这个包 a 的业务的常用的包的时候，建议写在peerDependencies里，避免重复下载/多个版本共存。

　　本篇文章主要介绍了 React hooks utils 库的背景以及 ahooks 的特点简介和整体结构，后续有更多精彩内容，欢迎大家继续关注。