每个 React 开发者都需要的 10 个浏览器 API Hooks

学习如何在 React 中使用 Geolocation、Clipboard、Fullscreen、Media Queries 等浏览器 API,借助 ReactUse 提供的简洁、可复用的 Hooks。

原文发布于 reactuse.com

现代浏览器提供了强大的 API,包括地理定位、剪贴板访问、全屏模式、网络状态等等。在 React 中直接使用它们比应有的难度更大。你需要防范服务端渲染、添加和移除事件监听器、处理权限,以及在卸载时清理。将这些工作乘以你的应用涉及的每个浏览器 API,你就有了大量重复且容易出错的代码。

ReactUse 通过一个包含 100 多个 Hooks 的库来解决这个问题,将浏览器 API 封装为简洁的、SSR 安全的、TypeScript 友好的接口。只需安装一次,按需导入:

bash 复制代码
npm i @reactuses/core

1. useMediaQuery -- 响应式设计

在 JavaScript 中响应 CSS 媒体查询。该 Hook 返回一个布尔值,在视口变化时实时更新。

tsx 复制代码
import { useMediaQuery } from "@reactuses/core";

function App() {
  const isMobile = useMediaQuery("(max-width: 768px)");
  return <div>{isMobile ? <MobileNav /> : <DesktopNav />}</div>;
}

2. useClipboard -- 复制到剪贴板

使用现代 Clipboard API 读写系统剪贴板。该 Hook 处理权限、HTTPS 要求和焦点状态边界情况。

tsx 复制代码
import { useClipboard } from "@reactuses/core";

function CopyButton({ text }: { text: string }) {
  const [clipboardText, copy] = useClipboard();
  return (
    <button onClick={() => copy(text)}>
      {clipboardText === text ? "Copied!" : "Copy"}
    </button>
  );
}

3. useGeolocation -- 用户位置

追踪用户的地理坐标,在卸载时自动清理 watchPosition 监听器。

tsx 复制代码
import { useGeolocation } from "@reactuses/core";

function LocationDisplay() {
  const { coordinates, error, isSupported } = useGeolocation();
  if (!isSupported) return <p>不支持地理定位。</p>;
  if (error) return <p>错误: {error.message}</p>;
  return <p>纬度: {coordinates.latitude}, 经度: {coordinates.longitude}</p>;
}

4. useFullscreen -- 全屏模式

对任意元素切换全屏。该 Hook 封装了 Fullscreen API,返回当前状态和控制函数。

tsx 复制代码
import { useRef } from "react";
import { useFullscreen } from "@reactuses/core";

function VideoPlayer() {
  const ref = useRef<HTMLDivElement>(null);
  const [isFullscreen, { toggleFullscreen }] = useFullscreen(ref);
  return (
    <div ref={ref}>
      <video src="/demo.mp4" />
      <button onClick={toggleFullscreen}>
        {isFullscreen ? "退出" : "全屏"}
      </button>
    </div>
  );
}

5. useNetwork -- 在线/离线状态

监控用户的网络连接。该 Hook 追踪在线/离线状态,在可用时还提供连接详情。

tsx 复制代码
import { useNetwork } from "@reactuses/core";

function NetworkBanner() {
  const { online, effectiveType } = useNetwork();
  if (!online) return <div className="banner">您已离线</div>;
  return <div>连接类型: {effectiveType}</div>;
}

6. useIdle -- 空闲检测

检测用户何时停止与页面交互。

tsx 复制代码
import { useIdle } from "@reactuses/core";

function IdleWarning() {
  const isIdle = useIdle(300_000); // 5 分钟
  return isIdle ? <div>你还在吗?</div> : null;
}

7. useDarkMode -- 深色模式切换

管理深色模式,包含系统偏好检测、localStorage 持久化和根元素自动类名切换。

tsx 复制代码
import { useDarkMode } from "@reactuses/core";

function ThemeToggle() {
  const [isDark, toggle] = useDarkMode({
    classNameDark: "dark",
    classNameLight: "light",
  });
  return (
    <button onClick={toggle}>
      {isDark ? "切换到浅色" : "切换到深色"}
    </button>
  );
}

8. usePermission -- 权限状态

查询浏览器权限的状态并实时响应变化。

tsx 复制代码
import { usePermission } from "@reactuses/core";

function CameraAccess() {
  const status = usePermission("camera");
  if (status === "denied") return <p>摄像头访问被拒绝。</p>;
  if (status === "prompt") return <p>我们需要摄像头权限。</p>;
  return <p>摄像头访问已授权。</p>;
}

9. useLocalStorage -- 持久化状态

useState 的替代方案,持久化到 localStorage。处理序列化、SSR 安全性、跨标签页同步和错误恢复。

tsx 复制代码
import { useLocalStorage } from "@reactuses/core";

function Settings() {
  const [lang, setLang] = useLocalStorage("language", "en");
  return (
    <select value={lang ?? "en"} onChange={(e) => setLang(e.target.value)}>
      <option value="en">English</option>
      <option value="es">Spanish</option>
      <option value="fr">French</option>
    </select>
  );
}

10. useEventListener -- 事件处理

将事件监听器附加到任何目标,自动清理,并提供 TypeScript 安全的事件类型。

tsx 复制代码
import { useEventListener } from "@reactuses/core";

function KeyLogger() {
  useEventListener("keydown", (event) => {
    console.log("按键:", event.key);
  });
  return <p>按任意键...</p>;
}

手动实现 vs. ReactUse

关注点 手动实现 ReactUse Hook
SSR 安全检查 到处添加 typeof window !== "undefined" 内置
事件监听器清理 useEffect + removeEventListener 自动
TypeScript 事件类型 手动泛型约束 完全类型化
localStorage 序列化 JSON.parse/stringify + 错误处理 自动
跨标签页同步 手动 storage 事件监听 内置

对于单个 Hook 来说节省量不大。但在整个应用中使用五个或更多浏览器 API 时,ReactUse 消除了数百行防御性代码。


ReactUse 提供了 100 多个 React Hooks。查看全部 →

相关推荐
y = xⁿ4 分钟前
小林coding:HashMap的原理,ConcurrentHashMap实现逻辑,1.8并发是如何超越1.7的
java·面试·hash
GISer_Jing10 分钟前
前端架构师视角:Electron 知识框架全解析(含实战+面试)
前端·面试·electron
全栈练习生13 分钟前
封装数字滚动动画函数
前端
不爱吃炸鸡柳14 分钟前
[特殊字符]C/C++内存管理深度解剖:从内存布局到new/delete底层,吃透面试必考核心
c语言·c++·面试
zzginfo15 分钟前
JavaScript 解构赋值
开发语言·javascript·ecmascript
邂逅星河浪漫40 分钟前
【JavaScript】==和===区别详解
java·javascript·==·===
Lzh编程小栈41 分钟前
数据结构与算法之队列深度解析:循环队列+C 语言硬核实现 + 面试考点全梳理
c语言·开发语言·汇编·数据结构·后端·算法·面试
TON_G-T1 小时前
useEffect为什么会触发死循环
java·服务器·前端
Aurorar0rua1 小时前
CS50 x 2024 Notes C - 02
前端
海参崴-1 小时前
C++代码格式规范
java·前端·c++