您的位置:首页 > 文旅 > 美景 > 新乡网站建设制作公司_乐拾seo_鞍山做网站的公司_seo关键词的优化技巧

新乡网站建设制作公司_乐拾seo_鞍山做网站的公司_seo关键词的优化技巧

2025/9/12 3:28:15 来源:https://blog.csdn.net/qq_40860137/article/details/147294275  浏览:    关键词:新乡网站建设制作公司_乐拾seo_鞍山做网站的公司_seo关键词的优化技巧
新乡网站建设制作公司_乐拾seo_鞍山做网站的公司_seo关键词的优化技巧

实战题:实现一个useWindowSize或useFetch

自定义 Hook 设计实战:useWindowSizeuseFetch 实现详解


一、useWindowSize:实时监听窗口尺寸
1. 基础实现(TypeScript 版)
import { useState, useEffect } from 'react';// 定义返回值的类型
type WindowSize = {width: number;height: number;
};const useWindowSize = (): WindowSize => {// 处理 SSR 环境(如 Next.js)const isSSR = typeof window === 'undefined';// 初始化状态(兼容 SSR)const [windowSize, setWindowSize] = useState<WindowSize>(() => ({width: isSSR ? 0 : window.innerWidth,height: isSSR ? 0 : window.innerHeight,}));useEffect(() => {if (isSSR) return; // 服务端无需执行const handleResize = () => {setWindowSize({width: window.innerWidth,height: window.innerHeight,});};// 立即触发一次以获取初始值handleResize();// 添加事件监听window.addEventListener('resize', handleResize);// 清理函数:移除监听return () => {window.removeEventListener('resize', handleResize);};}, [isSSR]); // 依赖项为 isSSR(仅挂载时执行)return windowSize;
};// 使用示例
const ResponsiveComponent = () => {const { width, height } = useWindowSize();return <div>当前窗口尺寸:{width}px × {height}px</div>;
};
2. 进阶优化:防抖处理
// 防抖工具函数
const debounce = (fn: Function, delay: number) => {let timer: NodeJS.Timeout;return (...args: any[]) => {clearTimeout(timer);timer = setTimeout(() => fn(...args), delay);};
};// 修改 useEffect 部分
useEffect(() => {// ...其他代码同前const debouncedResize = debounce(handleResize, 200);window.addEventListener('resize', debouncedResize);return () => window.removeEventListener('resize', debouncedResize);
}, [isSSR]);

二、useFetch:通用数据请求 Hook
1. 完整实现(支持 TypeScript 泛型)
import { useState, useEffect } from 'react';// 定义状态类型
type FetchState<T> = {data: T | null;isLoading: boolean;error: Error | null;
};// 请求配置类型
type FetchOptions = RequestInit & {timeout?: number;
};const useFetch = <T,>(url: string,options?: FetchOptions
): FetchState<T> => {const [state, setState] = useState<FetchState<T>>({data: null,isLoading: true,error: null,});useEffect(() => {const controller = new AbortController();const { signal } = controller;let timeoutId: NodeJS.Timeout;const fetchData = async () => {try {// 设置超时if (options?.timeout) {timeoutId = setTimeout(() => {controller.abort();setState({data: null,isLoading: false,error: new Error('请求超时'),});}, options.timeout);}const response = await fetch(url, {...options,signal,});if (!response.ok) {throw new Error(`HTTP 错误 ${response.status}`);}const data: T = await response.json();setState({ data, isLoading: false, error: null });} catch (error) {// 忽略已取消的请求错误if (error.name !== 'AbortError') {setState({data: null,isLoading: false,error: error as Error,});}} finally {clearTimeout(timeoutId);}};fetchData();// 清理函数:取消请求return () => {controller.abort();clearTimeout(timeoutId);};}, [url, options?.timeout]); // 依赖项:URL 和超时时间return state;
};// 使用示例
interface User {id: number;name: string;
}const UserList = () => {const { data, isLoading, error } = useFetch<User[]>('/api/users', {timeout: 5000,});if (isLoading) return <div>加载中...</div>;if (error) return <div>错误:{error.message}</div>;return (<ul>{data?.map((user) => (<li key={user.id}>{user.name}</li>))}</ul>);
};
2. 关键功能解析
特性实现方式
请求取消AbortController + signal 参数
超时处理setTimeout + 自动取消请求
类型安全泛型 <T> 定义响应数据类型
错误处理区分网络错误、HTTP 状态码错误、超时错误
SSR 兼容无需特殊处理(浏览器 API 在服务端不会执行)

三、设计原则与最佳实践
1. 通用 Hook 设计规范

单一职责
useWindowSize 只关注窗口尺寸变化
useFetch 仅处理数据请求生命周期

明确输入输出

// useWindowSize:无需参数,返回尺寸对象
const { width } = useWindowSize();// useFetch:接收 URL 和配置,返回状态对象
const { data } = useFetch<User>('/api/user');

副作用清理

// 组件卸载时移除监听器/取消请求
useEffect(() => () => {window.removeEventListener('resize', handleResize);controller.abort();
}, []);
2. 性能优化策略

防抖/节流

// 避免 resize 事件高频触发状态更新
const debouncedResize = debounce(handleResize, 200);

条件执行

// 仅在 URL 变化时发起新请求
useEffect(() => {if (!url) return;fetchData();
}, [url]);

记忆化配置

// 使用 useMemo 避免重复触发请求
const options = useMemo(() => ({ timeout: 5000 }), []);
const { data } = useFetch(url, options);

四、对比总结
Hook核心场景关键技术点优化方向
useWindowSize响应式布局、图表自适应事件监听、SSR 兼容、防抖动态阈值判断(如移动端横竖屏)
useFetch数据列表加载、表单提交请求取消、错误处理、泛型支持缓存策略(SWR/React Query)

五、实战技巧
  1. 组合使用 Hooks

    // 响应式布局 + 数据加载
    const { width } = useWindowSize();
    const isMobile = width < 768;
    const { data } = useFetch<Article[]>(isMobile ? '/mobile-api' : '/desktop-api');
    
  2. 扩展 useFetch
    • 添加重试机制
    • 支持 JWT 自动刷新
    • 集成全局 Loading 状态管理

  3. 测试策略
    • 使用 Jest 模拟 window.resize 事件
    • 利用 msw 模拟 API 请求

通过合理设计自定义 Hook,可以显著提升代码复用率与可维护性。建议将通用逻辑抽象为 Hook,并通过文档明确使用约束。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com