编写自己的 Hooks
自定义 Hook 的本质不是“复用 UI”,而是复用状态逻辑:订阅、缓存、派生、节流/防抖、同步外部系统…… 当你发现多个组件里出现了相同的 Hook 组合与 Effect 逻辑,就该考虑抽出去。
例子:抽取“在线状态”逻辑
这个逻辑包含 State + Effect + 清理,非常适合封装成 Hook,然后在多个组件里复用。
TypeScript
import { useEffect, useState } from 'react';
function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
function onOnline() {
setIsOnline(true);
}
function onOffline() {
setIsOnline(false);
}
window.addEventListener('online', onOnline);
window.addEventListener('offline', onOffline);
return () => {
window.removeEventListener('online', onOnline);
window.removeEventListener('offline', onOffline);
};
}, []);
return isOnline;
}
export default function StatusBar() {
const isOnline = useOnlineStatus();
return <p>{isOnline ? '在线' : '离线'}</p>;
}常见模式:useDebouncedValue
防抖在搜索输入、自动保存、筛选列表里很常见。
TypeScript
import { useEffect, useState } from 'react';
export function useDebouncedValue<T>(value: T, delayMs: number) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const id = window.setTimeout(() => setDebounced(value), delayMs);
return () => window.clearTimeout(id);
}, [value, delayMs]);
return debounced;
}常见误区
- 把组件渲染/样式也塞进 Hook:Hook 应该负责逻辑,UI 交给组件。
- 在 Hook 里根据条件调用 Hook:违反 Hooks 规则,会导致状态错位。
- Hook 返回值不稳定导致子组件频繁渲染:必要时用
useMemo/useCallback。
下一步
- 了解更多自定义 Hook 的写法与实践:自定义 Hooks。
- 需要与外部系统同步时:使用 Effect 同步。
动手练习
运行并修改下面的组件,熟悉交互式示例的编辑与预览。
🌐浏览器运行