/**
* React 性能追踪 Hooks
* 封装 performanceMonitor 工具,提供 React 友好的性能追踪 API
*/
import { useEffect, useRef, useCallback } from 'react';
import { performanceMonitor } from '@utils/performanceMonitor';
/**
* usePerformanceMark 返回值类型
*/
export interface UsePerformanceMarkReturn {
/** 标记时间点 */
mark: (suffix: string) => void;
/** 测量并记录到 performanceMonitor */
measure: (startSuffix: string, endSuffix: string, name?: string) => number | null;
/** 获取测量值(不记录) */
getMeasure: (startSuffix: string, endSuffix: string) => number | null;
}
/**
* usePerformanceTracker - 自动追踪组件渲染性能
*
* @param componentName - 组件名称,用于标记
* @param options - 配置选项
*
* @example
* ```tsx
* function MyComponent() {
* usePerformanceTracker('MyComponent');
* return
...
;
* }
* ```
*
* 自动标记:
* - {componentName}-mount: 组件挂载时
* - {componentName}-rendered: 首次渲染完成
* - {componentName}-unmount: 组件卸载时
*/
export function usePerformanceTracker(
componentName: string,
options: { trackRender?: boolean } = {}
): void {
const { trackRender = true } = options;
const hasMounted = useRef(false);
// 首次渲染时立即标记(同步)
if (!hasMounted.current) {
performanceMonitor.mark(`${componentName}-mount`);
}
useEffect(() => {
if (!hasMounted.current) {
hasMounted.current = true;
// 渲染完成标记(在 useEffect 中,表示 DOM 已更新)
if (trackRender) {
performanceMonitor.mark(`${componentName}-rendered`);
performanceMonitor.measure(
`${componentName}-mount`,
`${componentName}-rendered`,
`${componentName} 渲染`
);
}
}
// 组件卸载时标记
return () => {
performanceMonitor.mark(`${componentName}-unmount`);
};
}, [componentName, trackRender]);
}
/**
* usePerformanceMark - 手动标记自定义操作的性能
*
* @param prefix - 标记前缀,用于区分不同操作
* @returns 包含 mark、measure、getMeasure 方法的对象
*
* @example
* ```tsx
* function MyComponent() {
* const { mark, getMeasure } = usePerformanceMark('api-call');
*
* const handleFetch = async () => {
* mark('start');
* await fetchData();
* mark('end');
* const duration = getMeasure('start', 'end');
* console.log('API耗时:', duration, 'ms');
* };
*
* return ;
* }
* ```
*/
export function usePerformanceMark(prefix: string): UsePerformanceMarkReturn {
const mark = useCallback(
(suffix: string) => {
performanceMonitor.mark(`${prefix}-${suffix}`);
},
[prefix]
);
const measure = useCallback(
(startSuffix: string, endSuffix: string, name?: string) => {
return performanceMonitor.measure(
`${prefix}-${startSuffix}`,
`${prefix}-${endSuffix}`,
name || `${prefix}: ${startSuffix} → ${endSuffix}`
);
},
[prefix]
);
const getMeasure = useCallback(
(startSuffix: string, endSuffix: string) => {
return performanceMonitor.measure(
`${prefix}-${startSuffix}`,
`${prefix}-${endSuffix}`
);
},
[prefix]
);
return { mark, measure, getMeasure };
}
export default usePerformanceTracker;