工具 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>