工具 Hook
useInterval、useAnimationFrame、useTween、useSpring、useMeasure、useBreakpoint 與 useLocalStorage。
Text.js 提供計時器、動畫、測量與資料持久化的 Hook。計時器與動畫會配合渲染器的影格節奏。
計時器
useInterval(refresh, live ? 1000 : null);useTimeout(() => setHint(false), 3000);兩者一律呼叫最新的回呼函式。null 會停止計時器。
useAnimationFrame
useAnimationFrame((delta, elapsed) => setPhase(elapsed / 1000), { isActive: playing });useAnimationFrame 在每個影格時段觸發一次。Text.js 每秒輸出約 15 個影格,因此加快動畫只會將 CPU 資源花在永遠不會記錄的影格上。相同頻率的迴圈共用一個計時器,並在輸出暫停時停止。
useTween 與 useSpring
const width = useTween(open ? 32 : 0, { duration: 240, easing: "easeOutCubic" });const offset = useSpring(selected * 2);兩者都會回傳以動畫方式趨近目標的數值,並在數值穩定後停止更新。easings 包含 linear、easeOutCubic、easeInOutCubic、easeOutExpo 等緩動函式。
useMeasure
const [ref, { width, height }] = useMeasure();return <Box ref={ref} className="grow">{width > 80 ? <Wide /> : <Narrow />}</Box>;版面配置在 React 提交後執行,因此尺寸會晚一個影格才取得。只有尺寸改變時才會重新渲染。
useBreakpoint
const { breakpoint, up } = useBreakpoint();return up("md") ? <TwoColumns /> : <OneColumn />;| Breakpoint | 欄數 |
|---|---|
xs | 0 |
sm | 60 |
md | 80 |
lg | 110 |
xl | 140 |
斷點以欄數為單位。將自訂門檻值作為引數傳入。
useLocalStorage
const [theme, setTheme] = useLocalStorage("theme", "geistDark");useLocalStorage 將 JSON 儲存在 localStorage 中,在瀏覽器以外的環境則儲存在記憶體中。共用同一個鍵的 Hook 會保持同步,跨分頁也一樣。
useClipboard
const { copy, copied } = useClipboard();useKeymap({ y: { label: "Copy id", run: () => copy(deployment.id) } });return <Text color="muted">{copied ? "Copied" : deployment.id}</Text>;<FocusScope>
<FocusScope> 是不可見的焦點邊界。啟用 trap 時,Tab 與 useInput 都會限制在邊界內,行為與沒有覆蓋層的 <Modal> 完全相同。
<FocusScope trap={editing}> <Input autoFocus /></FocusScope>