React 自定义 Hook 的应用场景与实现规范
请说明自定义 Hook 的命名规范、实现规则,并举例实现一个 useDebounce 和 useLocalStorage Hook。
回答
苦行僧
自定义 Hook 规范:
- 命名必须以
use开头(React 约定,lint 规则检查) - 内部可调用其他 Hook(useState/useEffect/useRef 等)
- 每次渲染时按相同顺序调用(不能放在条件/循环中)
- 自定义 Hook 之间可以互相调用
useDebounce:
function useDebounce(value, delay = 300) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debouncedValue;
}
// 使用
const debouncedSearch = useDebounce(searchTerm, 500);
useEffect(() => {
fetchSearch(debouncedSearch);
}, [debouncedSearch]);
useLocalStorage:
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch {
return initialValue;
}
});
const setValue = useCallback((value) => {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
}, [key, storedValue]);
return [storedValue, setValue];
}
其他常见自定义 Hook:
useWindowSize— 窗口尺寸监听useFetch— 数据请求+loading+error 状态管理useIntersectionObserver— 元素可见性检测useEventListener— 事件绑定与清理useMediaQuery— CSS Media Query 匹配