video-flow-b/app/hooks/useUpdateEffect.ts

58 lines
1.3 KiB
TypeScript

import { useEffect, useRef, EffectCallback, DependencyList } from "react";
type Mode = "debounce" | "throttle" | "none";
interface Options {
mode?: Mode;
delay?: number; // 毫秒
}
/**
* useUpdateEffect - 统一版
* 1. 跳过首次执行
* 2. 可选防抖/节流
*/
export function useUpdateEffect(
effect: EffectCallback,
deps: DependencyList,
options: Options = { mode: "none", delay: 0 }
) {
const { mode = "none", delay = 0 } = options;
const isFirstRender = useRef(true);
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const lastRunTimeRef = useRef<number>(0);
useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
if (mode === "none" || delay <= 0) {
return effect();
}
if (mode === "debounce") {
if (timerRef.current) clearTimeout(timerRef.current);
timerRef.current = setTimeout(() => {
effect();
}, delay);
}
if (mode === "throttle") {
const now = Date.now();
if (now - lastRunTimeRef.current >= delay) {
effect();
lastRunTimeRef.current = now;
}
}
return () => {
if (mode === "debounce" && timerRef.current) {
clearTimeout(timerRef.current);
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);
}