React-Use套件
react-use 套件
TL;DRreact-use 是 React Hooks 集合,提供 100+ 個常用 hook(useDebounce / useLocalStorage / useOnClickOutside / useWindowSize 等)。減少重複實作的 utility hooks。注意 useWheel 屬於 react-use-gesture 不是 react-use,容易搞混。
安裝
npm install react-use
最常用的 Hooks(精選)
State / Storage
| Hook | 用途 |
|---|---|
useToggle | true/false 切換 |
useCounter | 計數器(inc / dec / set) |
useLocalStorage | 綁定 localStorage 的 state |
useSessionStorage | 同上,sessionStorage 版 |
usePrevious | 取上一次 render 的值 |
useFirstMountState | 判斷是否為首次 render |
UI / DOM
| Hook | 用途 |
|---|---|
useClickAway | 點擊元素外部 觸發 |
useHover | 是否 hover |
useFocus / useFocusWithin | focus 狀態 |
useKey | 監聽某個 key |
useWindowSize | 視窗尺寸(會跟著 resize) |
useScroll | 滾動位置 |
useIntersection | IntersectionObserver wrapper |
Lifecycle / Async
| Hook | 用途 |
|---|---|
useDebounce | debounce 一個 effect |
useThrottle | throttle 一個 effect |
useTimeout / useInterval | 安全的計時器(會自動 cleanup) |
useMount / useUnmount | mount / unmount 一次性 effect |
useUpdateEffect | 跳過首次 render 的 effect |
useAsync | 處理 async 函式 + state |
Browser API
| Hook | 用途 |
|---|---|
useNetworkState | 網路連線狀態 |
useBattery | 電池資訊 |
useGeolocation | 地理位置 |
useMedia | media query 監聽 |
useClipboard | 剪貼簿讀寫 |
範例:useLocalStorage
最常用、最香的一個:
import { useLocalStorage } from 'react-use';
function Settings() {
const [theme, setTheme] = useLocalStorage('theme', 'light');
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle ({theme})
</button>
);
}
自動 JSON 序列化、自動同步多分頁、refresh 後保留。比自己寫 useEffect + getItem/setItem 省 20 行。
範例:useClickAway
import { useRef } from 'react';
import { useClickAway } from 'react-use';
function Dropdown({ onClose }: { onClose: () => void }) {
const ref = useRef<HTMLDivElement>(null);
useClickAway(ref, onClose);
return <div ref={ref}>下拉選單內容</div>;
}
下拉選單、modal、popover 必備。自己實作要處理 mousedown vs click、touch 事件、stopPropagation 等,套件已搞定。
範例:useDebounce
import { useState } from 'react';
import { useDebounce } from 'react-use';
function Search() {
const [input, setInput] = useState('');
const [debounced, setDebounced] = useState('');
useDebounce(() => {
setDebounced(input);
// 觸發 API 搜尋
fetch(`/api/search?q=${input}`);
}, 500, [input]);
return <input value={input} onChange={(e) => setInput(e.target.value)} />;
}
500ms 沒打字才觸發 API,標準 search-as-you-type pattern。
⚠️ 常見搞混:useWheel 不在這裡!
// ❌ 這個會錯,react-use 沒有 useWheel
import { useWheel } from 'react-use';
// ✅ useWheel 在 @use-gesture/react(原 react-use-gesture)
import { useWheel } from '@use-gesture/react';
npm install @use-gesture/react
@use-gesture 是 同作者 的另一個套件,專做手勢 / 拖曳 / 滾輪等複雜互動。
useWheel 範例:圖片縮放
import { useWheel } from '@use-gesture/react';
import { useState } from 'react';
function ZoomImage({ src }: { src: string }) {
const [scale, setScale] = useState(1);
const bind = useWheel(({ delta: [, dy] }) => {
setScale((prev) => {
const next = prev + dy / 100;
return Math.min(Math.max(next, 0.1), 3); // 0.1 ~ 3 之間
});
});
return (
<div {...bind()} style={{ transform: `scale(${scale})` }}>
<img src={src} alt="" />
</div>
);
}
bind() 是個函式,要呼叫才會回傳 props 物件,別忘了括號。
套件大小考量
react-use 的 tree-shaking 友善,只 import 用到的 hook,bundle 不會吃整包:
// ✅ 只進 useDebounce 那一個
import { useDebounce } from 'react-use';
不過如果只用 1-2 個 hook,可以考慮直接抄 source 進專案,省一個依賴。
替代選擇
| 套件 | 規模 | 特色 |
|---|---|---|
| react-use | 100+ hooks | 綜合萬用 |
| usehooks-ts | ~30 hooks | TypeScript first、輕 |
| ahooks | 60+ hooks | 阿里出品、商業導向 |
| react-use-gesture / @use-gesture | 專注手勢 | 拖曳、滾輪、捏合 |
2026 年建議個人專案 / 小工具 → usehooks-ts(輕、TS 完整)。需要大量瀏覽器 API hook → react-use。手勢互動 → @use-gesture。