2026年3月17日

ReactUse vs usehooks-ts:该选哪个 React Hooks 库?

ReactUse@reactuses/core)和 usehooks-ts 都是以 TypeScript 为先的 React Hooks 库,旨在减少组件中的样板代码。它们有着相似的理念——提供简洁、可复用的 Hooks 和出色的类型推断——但在覆盖范围、SSR 处理和浏览器 API 支持方面存在显著差异。

我们维护着 ReactUse,所以有自己的立场。但我们已尽力做到公平,承认 usehooks-ts 的优势。

概览对比

特性ReactUseusehooks-ts
Hook 数量100+~30
TypeScript 优先
Tree-shaking
SSR 安全是(内置 isBrowser 防护)各 Hook 不一
每个 Hook 体积
分类体系浏览器、状态、元素、传感器、动画、副作用通用
交互式演示否(展示源码)
浏览器 API Hooks地理定位、剪贴板、全屏、语音、通知等有限
DOM 观察者 HooksIntersectionObserver、ResizeObserver、MutationObserver仅 IntersectionObserver
维护状态活跃活跃

代码对比:useLocalStorage

ReactUse:

import { useLocalStorage } from "@reactuses/core";

function Settings() {
  const [theme, setTheme] = useLocalStorage("theme", "light");
  return (
    <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
      当前: {theme}
    </button>
  );
}

usehooks-ts:

import { useLocalStorage } from "usehooks-ts";

function Settings() {
  const [theme, setTheme] = useLocalStorage("theme", "light");
  return (
    <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
      当前: {theme}
    </button>
  );
}

两者的 API 几乎完全相同,都返回模仿 useState[value, setter] 元组。这是 usehooks-ts 最大的优点之一——API 简洁且熟悉。

代码对比:useMediaQuery

ReactUse:

import { useMediaQuery } from "@reactuses/core";

function ResponsiveLayout() {
  const isMobile = useMediaQuery("(max-width: 768px)");
  return <div>{isMobile ? "移动端" : "桌面端"}</div>;
}

usehooks-ts:

import { useMediaQuery } from "usehooks-ts";

function ResponsiveLayout() {
  const isMobile = useMediaQuery("(max-width: 768px)");
  return <div>{isMobile ? "移动端" : "桌面端"}</div>;
}

同样非常相似。两个库都返回布尔值。区别在 SSR 层——ReactUse 内部对 window.matchMedia 调用进行了防护,在服务端渲染时安全地返回 false,无需你做额外处理。

代码对比:useDebounce

ReactUse:

import { useDebounceFn } from "@reactuses/core";

function Search() {
  const { run } = useDebounceFn((query: string) => {
    fetch(`/api/search?q=${query}`);
  }, 300);

  return <input onChange={(e) => run(e.target.value)} />;
}

usehooks-ts:

import { useDebounceCallback } from "usehooks-ts";

function Search() {
  const debouncedFetch = useDebounceCallback((query: string) => {
    fetch(`/api/search?q=${query}`);
  }, 300);

  return <input onChange={(e) => debouncedFetch(e.target.value)} />;
}

两者都能很好地工作。ReactUse 还额外提供 useThrottleFnuseDebouncedValueuseThrottledValue,满足更细粒度的控制需求。

SSR 安全性

这是两个库之间最重要的实际差异。

ReactUse 在每个访问 windowdocumentnavigator 的 Hook 中内部检查 isBrowser。你永远不需要自己编写 typeof window !== "undefined"。这意味着 ReactUse 的 Hooks 在 Next.js、Remix 和任何其他 SSR 框架中开箱即用。

usehooks-ts 的 SSR 处理不够一致。部分 Hook 做了浏览器 API 防护,部分没有。如果你在构建 SSR 应用,可能需要在 usehooks-ts 的 Hook 外层添加自己的防护或使用动态导入,这增加了复杂度。

何时选择 usehooks-ts

usehooks-ts 在以下场景是不错的选择:

  • 你只需要少量常用 Hooks(localStorage、media query、debounce、click outside)
  • 你的项目是纯客户端 SPA,没有 SSR 需求
  • 你希望依赖体积尽可能小
  • 你喜欢在文档中直接阅读源码——usehooks-ts 展示了每个实现

usehooks-ts 在它的领域做得很好。实现简洁、可读、易理解。对于只需少量工具的小项目,它完全合理。

何时选择 ReactUse

ReactUse 更适合以下场景:

  • 你在构建可能现在或将来需要 SSR 的生产应用
  • 你需要基础之外的浏览器 API Hooks(地理定位、剪贴板、全屏、语音识别、电池状态、通知)
  • 你需要 DOM 观察者 Hooks(IntersectionObserver、ResizeObserver、MutationObserver、元素边界)
  • 你需要动画工具(useRafFn、useTransition、useInterval、useTimeout)
  • 你需要传感器 Hooks(useDeviceMotion、useDeviceOrientation、useMouse、useScroll)
  • 你希望用一个库覆盖 100+ 个场景,而非拼凑多个包

迁移指南:从 usehooks-ts 迁移到 ReactUse

如果你已在使用 usehooks-ts 并想迁移,过程很简单,因为两个库都遵循 [value, setter] 约定。

第一步:安装 ReactUse

npm i @reactuses/core

第二步:更新导入

usehooks-tsReactUse
useLocalStorageuseLocalStorage
useMediaQueryuseMediaQuery
useDebounceCallbackuseDebounceFn
useIntersectionObserveruseIntersectionObserver
useEventListeneruseEventListener
useOnClickOutsideuseClickOutside
useCopyToClipboarduseClipboard

第三步:移除 SSR 防护代码 ——ReactUse 在内部处理,你可以删除为 usehooks-ts Hooks 添加的所有 typeof window 检查。

安装

npm i @reactuses/core
import { useLocalStorage, useMediaQuery, useClipboard } from "@reactuses/core";

每个 Hook 都在 reactuse.com 上提供了在线演示、完整 API 参考和 TypeScript 定义。


今天就试试 ReactUse 吧。立即开始 →