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

目录
  • 引言
  • React hooks utils 库
  • ahooks
    • 简介
    • 特点
    • hooks 种类
  • ahooks 整体架构
    • 项目启动
    • 整体结构
    • hooks
  • 总结

引言

本文是深入浅出 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。如下所示:

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__ 文件夹,这个是用来写单元测试的。

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

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 的特点简介和整体结构,接下来会探索各个常见的 hooks 方法实现,敬请期待。

参考 ahooks 正式发布:值得拥抱的 React Hooks 工具库

更多关于hooks架构React工具库的资料请关注我们其它相关文章!

(0)

相关推荐

  • React Hooks与setInterval的踩坑问题小结

    目录 一.需求 二.解决方案 1.函数式更新 2.使用useRef 3.用useReducer 4.自定义的hooks 一.需求 我们希望有一个每一秒自动+1的定时器 function Counter() { let [count, setCount] = useState(0); useEffect(() => { let id = setInterval(() => { setCount(count + 1); }, 1000); return () => clearInterval

  • ahooks正式发布React Hooks工具库

    目录 起因 解法 共建 项目目标 品牌升级 社区开源 API 规范 示例演示 开发迭代 下一步 起因 从 React Hooks 正式发布到现在,越来越多的项目正在使用 Function Component 替代 Class Component,Hooks 这一新特性也逐渐被广泛的使用. 然而在实践的过程中,我们发现在很多常见的场景下,大部分逻辑是重复且可被复用的,如对数据请求的逻辑处理,对防抖节流的逻辑处理等,同样的代码经常会在同一个或不同的项目中被重复的编写 . 另一方面,由于 Hooks

  • ReactHooks批量更新state及获取路由参数示例解析

    目录 一.如何批量更新 控制台输出 二.Hooks如何获取路由参数 执行效果 一.如何批量更新 在[Hooks]中如果单独的进行状态的更新可能会导致页面的多次渲染: import { useState } from 'react'; import { unstable_batchedUpdates } from 'react-dom';//批量更新状态时使用 import React from 'react'; const Example = () => { const [count, setC

  • 详解react hooks组件间的传值方式(使用ts)

    目录 父传子 子传父 跨级组件(父传后代) 父传子 通过props传值,使用useState来控制state的状态值 父组件 Father.tsx里: 子组件 Child.tsx里: 展示效果: 子传父 跟react的方式一样,像子组件传入回调函数,通过接收子组件的返回值,再去更新父组件的state 父组件,Father.tsx里: 子组件,Child.tsx里: 展示效果: 子传父优化版,使用useCallback存放处理事件的函数 父组件,Father.tsx里: 子组件,Child.tsx

  • React从Class方式转Hooks详解

    目录 React Hooks 前言 Why Hooks ? For Class For Function Class & Hooks 对比 Hooks如何保存组件状态和使用生命周期? 1.useState:让函数具有维持状态的能力 2.useEffect:执行副作用 总结 React Hooks 前言 之前工作三年中一直在用class方式去写前端功能页面这些,其实接触hooks也是有一定时间了.在第一次接触的时候应该是看了一门关于electron+react的项目的课程的时候.当时主要是去看el

  • React Hooks使用常见的坑

    React Hooks 是 React 16.8 引入的新特性,允许我们在不使用 Class 的前提下使用 state 和其他特性.React Hooks 要解决的问题是状态共享,是继 render-props 和 higher-order components 之后的第三种状态逻辑复用方案,不会产生 JSX 嵌套地狱问题. 为什么会有Hooks? 介绍Hooks之前,首先要给大家说一下React的组件创建方式,一种是类组件,一种是纯函数组件,并且React团队希望,组件不要变成复杂的容器,最好

  • 教你在react中创建自定义hooks

    一.什么是自定义hooks 逻辑复用 简单来说就是使用自定义hook可以将某些组件逻辑提取到可重用的函数中. 自定义hook是一个从use开始的调用其他hook的Javascript函数. 二.不使用自定义hook时 例1:当我们整个页面需要获取用户鼠标移动的坐标时,不使用hook的代码,我们可以这样写 const [position, setPosition] = useState({ x: 0, y: 0 }) useEffect(() => { const move = (e) => {

  • ahooks整体架构及React工具库源码解读

    目录 引言 React hooks utils 库 ahooks 简介 特点 hooks 种类 ahooks 整体架构 项目启动 整体结构 hooks 总结 引言 本文是深入浅出 ahooks 源码系列文章的第一篇,这个系列的目标主要有以下几点: 加深对 React hooks 的理解. 学习如何抽象自定义 hooks.构建属于自己的 React hooks 工具库. 培养阅读学习源码的习惯,工具库是一个对源码阅读不错的选择. 注:本系列对 ahooks 的源码解析是基于 v3.3.13.自己

  • React之echarts-for-react源码解读

    目录 前言 从与原生初始化对比开始 陷阱-默认值height为300px 主逻辑源码剖析 挂载渲染过程 更新渲染过程 卸载过程 项目依赖 后续 前言 在当前工业4.0和智能制造的产业升级浪潮当中,智慧大屏无疑是展示企业IT成果的最有效方式之一.然而其背后怎么能缺少ECharts的身影呢?对于React应用而言,直接使用ECharts并不是最高效且优雅的方式,而echarts-for-react则是针对React应用对ECharts进行轻量封装和增强的工具库. echarts-for-react的

  • Css-In-Js实现classNames库源码解读

    目录 引言 使用 源码阅读 兼容性 CommonJS AMD window 浏览器环境 实现 多个参数处理 参数类型处理 数组处理 对象处理 测试用例 Css-in-JS 示例 总结 引言 classNames是一个简单的且实用的JavaScript应用程序,可以有条件的将多个类名组合在一起.它是一个非常有用的工具,可以用来动态的添加或者删除类名. 仓库地址:classNames 使用 根据classNames的README,可以发现库的作者对这个库非常认真,文档和测试用例都非常齐全,同时还有有

  • python 制作网站筛选工具(附源码)

    一.思路 1.整体思路 2.代码思路 思路很简单,就是用python发送请求,提取响应体中的状态码加以判断,最后保存到本地txt文本中,以实现网站信息的筛选. 二.撰写代码 import time import requests import urllib3 from concurrent.futures import ThreadPoolExecutor #取源文件中的网址并且去重 def get_url(old_file): with open(old_file,'r',encoding='

  • python gui开发——制作抖音无水印视频下载工具(附源码)

    hello,大家好啊,失踪人口回归了 [捂脸]!本次使用tkinter撰写一篇 抖音无水印视频下载,目的很纯粹,就是为了设置 微信状态视频.本篇博文中,我会写下我的代码撰写思路以及想写设计流程,代码放在了第四节,工具打包好放在了 蓝奏云,慢慢看,后面有链接. 一.准备工作 本次要用到以下依赖库:re json os random tkinter threading requests pillow 其中后两个需要安装后使用 二.预览 0.复制抖音分享短链接 1.启动 2.运行 3.结果 (小姐姐挺

  • python基于tkinter制作无损音乐下载工具(附源码)

    继续写GUI,本次依然使用Tkinter设计一款图形界面,使用Tkinter做一款音乐下载软件,听起来听平常的,但是我这款软件能够下载 无损音乐下载软件,听起来不错吧,Let`s go! 一.准备工作 python Tkinter 二.预览 1.搜索 2.下载 3.结果 无损音乐就这样下载完了. 三.详细设计 这里仅展示我设计的整体思路. 四.源代码 4.1 Music_Search-v1.0.py from tkinter import * from tkinter import ttk fr

  • 史上最好用的远程桌面工具(附源码)

    大家都是用的哪一款远程控制工具呢? 向日葵确实还可以,支持多平台.跨网络,但是必须要注册 Oray账号才行.虽然与免费版,但是用过的都知道,还是得付费才管用! Teamviewer 现在也不咋滴了,感觉还不如向日好使. 还有一个大家肯定都知道,那就是 QQ远程桌面,想起鬼哥我以前就经常用这个功能帮妹子电脑激活软件啥的,那时的我还是个懵懂不经人事的少年(工具人)-- 就在上个礼拜,向日葵又提醒我快要过期了.叫我续费. 当时我就想着要不在GitHub上面找找吧,说不定有大佬开源的远程控制工具呢,要是

  • Golang标准库unsafe源码解读

    目录 引言 unsafe包 unsafe构成 type ArbitraryType int type Pointer *ArbitraryType 灵活转换 潜在的危险性 正确的使用姿势 错误的使用姿势 func Sizeof(x ArbitraryType) uintptr func Offsetof(x ArbitraryType) uintptr func Alignof(x ArbitraryType) uintptr 引言 当你阅读Golang源码时一定遇到过unsafe.Pointe

  • jQuery源码解读之extend()与工具方法、实例方法详解

    本文实例讲述了jQuery源码解读之extend()与工具方法.实例方法.分享给大家供大家参考,具体如下: 使用jQuery的时候会发现,jQuery中有的函数是这样使用的: $.get(); $.post(); $.getJSON(); 有些函数是这样使用的: $('div').css(); $('ul').find('li'); 有些函数是这样使用的: $('li').each(callback); $.each(lis,callback); 这里涉及到两个概念:工具方法与实例方法.通常我们

  • 模块一 GO语言基础知识-库源码文件

    你已经使用过 Go 语言编写了小命令(或者说微型程序)吗? 当你在编写"Hello, world"的时候,一个源码文件就足够了,虽然这种小玩意儿没什么用,最多能给你一点点莫名的成就感.如果你对这一点点并不满足,别着急,跟着学,我肯定你也可以写出很厉害的程序. 我们在上一篇的文章中学到了命令源码文件的相关知识,那么除了命令源码文件,你还能用 Go 语言编写库源码文件.那么什么是库源码文件呢? 在我的定义中,库源码文件是不能被直接运行的源码文件,它仅用于存放程序实体,这些程序实体可以被其他

随机推荐