757 字
4 分钟
优质 React Hook 开源库

先问一句:这个 Hook 值得引一个依赖吗#

一个 useLocalStorage 大概二十行,一个 useWindowSize 十行以内。这类需求自己写更快,也少一个要跟版本的依赖。

值得引库的是三种情况:逻辑本身复杂(表单校验、虚拟列表、请求缓存);涉及大量浏览器 API 的边界(剪贴板、媒体查询、各类传感器);你需要 SSR 与水合的安全性,而这些坑别人已经踩过。

选的时候看四件事:仓库最近的提交时间、TypeScript 类型是否完整、SSR 相关 issue 怎么处理、以及能不能按需引入。

通用 Hook#

ahooks#

60 多个 Hook,按请求、存储、DOM、传感器等分类,中文文档完善。仓库 https://github.com/alibaba/hooks。

它的 useRequest 把加载态、缓存、轮询、取消都包了:

import { useRequest } from 'ahooks'
function User() {
const { data, loading, error } = useRequest(() =>
fetch('/api/user').then(res => res.json())
)
if (loading) return <div>加载中……</div>
if (error) return <div>错误:{error.message}</div>
return <div>用户名:{data?.name}</div>
}

react-use#

覆盖面最广的一类,按 Browser、State、Element、Effect、Sensor 等分类,浏览器 API 的封装很多。仓库 https://github.com/streamich/react-use。

import { useLocalStorage } from 'react-use'
function App() {
const [theme, setTheme] = useLocalStorage('theme', 'light')
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
切换主题:{theme}
</button>
)
}

@react-hookz/web#

类型更严的通用库,零依赖,带 useAsync、useLocalStorageValue 这类强类型封装。仓库 https://github.com/react-hookz/web。

import { useAsync } from '@react-hookz/web'
function Data() {
const { result, error, status } = useAsync(async () => {
const res = await fetch('/api/data')
return res.json()
}, [])
if (status === 'loading') return <div>加载中……</div>
if (status === 'error') return <div>错误:{error.message}</div>
return <div>{JSON.stringify(result)}</div>
}

表单#

react-hook-form#

核心是「非受控」,值靠 ref 收集,所以打字时不会整个表单重渲染。仓库 https://github.com/react-hook-form/react-hook-form。

import { useForm } from 'react-hook-form'
function Login() {
const { register, handleSubmit, formState: { errors } } = useForm()
const onSubmit = data => console.log(data)
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('email', { required: '邮箱必填' })} placeholder="邮箱" />
{errors.email && <p>{errors.email.message}</p>}
<button type="submit">登录</button>
</form>
)
}

服务端数据#

TanStack Query#

管的是「服务端状态」这一层:缓存、失效、重试、后台刷新、分页与无限滚动。仓库 https://github.com/TanStack/query。

这里要盯住版本。旧写法里的 loading 在 v5 已经不在返回值里了:

import { useQuery } from '@tanstack/react-query'
function Posts() {
const { data, isPending, error } = useQuery({
queryKey: ['posts'],
queryFn: () =>
fetch('https://jsonplaceholder.typicode.com/posts').then(res => res.json()),
})
if (isPending) return <div>加载中……</div>
if (error) return <div>错误:{error.message}</div>
return <ul>{data.map(post => <li key={post.id}>{post.title}</li>)}</ul>
}

v5 把状态标志拆成了几个:isPending 表示还没有数据,isFetching 表示后台正在刷新;error 是对象,不是字符串。这几个的准确语义以官方迁移指南为准,抄示例之前先对一遍版本。

几条提醒#

同一个用途别同时引两个库。两个都管请求缓存时,失效时机很难对齐,排查起来很费时间。

库提供的 Hook 依然受 Hook 规则约束:只能在组件或自定义 Hook 的顶层调用,别放进条件或循环。

Star 数与维护状态都会变,本文不写「首选」「之王」这类结论。选之前看一眼仓库最近的提交和 issue 的处理情况。

第 39 篇,共 39 篇本文属于系列

优质 React Hook 开源库
https://www.choria.top/posts/react-hook-libraries/
作者
乔瑞雅·克林威尔
发布于
2026-05-02
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取

最后更新于 ,距今已过 190 天

部分内容可能已过时