Skip to content

Commit 1693516

Browse files
committed
chore: use hooks
1 parent bf0ddfe commit 1693516

3 files changed

Lines changed: 49 additions & 51 deletions

File tree

src/UniqueProvider/index.tsx

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,25 @@
11
import * as React from 'react';
22
import { UniqueContext, type UniqueContextProps } from '../context';
3+
import useDelay from '../hooks/useDelay';
34

45
export interface UniqueProviderProps {
56
children: React.ReactNode;
67
}
78

89
const UniqueProvider = ({ children }: UniqueProviderProps) => {
910
const [target, setTarget] = React.useState<HTMLElement | null>(null);
10-
const delayRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
11-
12-
const clearDelay = () => {
13-
if (delayRef.current) {
14-
clearTimeout(delayRef.current);
15-
delayRef.current = null;
16-
}
17-
};
11+
const delayInvoke = useDelay();
1812

1913
const show = (targetElement: HTMLElement, delay: number) => {
20-
clearDelay();
21-
22-
if (delay === 0) {
14+
delayInvoke(() => {
2315
setTarget(targetElement);
24-
} else {
25-
delayRef.current = setTimeout(() => {
26-
setTarget(targetElement);
27-
}, delay * 1000);
28-
}
16+
}, delay);
2917
};
3018

3119
const hide = (targetElement: HTMLElement, delay: number) => {
32-
clearDelay();
33-
34-
if (delay === 0) {
20+
delayInvoke(() => {
3521
setTarget(null);
36-
} else {
37-
delayRef.current = setTimeout(() => {
38-
setTarget(null);
39-
}, delay * 1000);
40-
}
22+
}, delay);
4123
};
4224

4325
const contextValue = React.useMemo<UniqueContextProps>(() => ({

src/hooks/useDelay.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import * as React from 'react';
2+
3+
export default function useDelay() {
4+
const delayRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
5+
6+
const clearDelay = () => {
7+
if (delayRef.current) {
8+
clearTimeout(delayRef.current);
9+
delayRef.current = null;
10+
}
11+
};
12+
13+
const delayInvoke = (callback: () => void, delay: number) => {
14+
clearDelay();
15+
16+
if (delay === 0) {
17+
callback();
18+
} else {
19+
delayRef.current = setTimeout(() => {
20+
callback();
21+
}, delay * 1000);
22+
}
23+
};
24+
25+
// Clean up on unmount
26+
React.useEffect(() => {
27+
return () => {
28+
clearDelay();
29+
};
30+
}, []);
31+
32+
return delayInvoke;
33+
}

src/index.tsx

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { TriggerContextProps } from './context';
1313
import TriggerContext, { UniqueContext } from './context';
1414
import useAction from './hooks/useAction';
1515
import useAlign from './hooks/useAlign';
16+
import useDelay from './hooks/useDelay';
1617
import useWatch from './hooks/useWatch';
1718
import useWinClick from './hooks/useWinClick';
1819
import type {
@@ -303,17 +304,7 @@ export function generateTrigger(
303304
const lastTriggerRef = React.useRef<boolean[]>([]);
304305
lastTriggerRef.current = [];
305306

306-
const internalTriggerOpen = useEvent((nextOpen: boolean, delay: number = 0) => {
307-
// If UniqueContext exists, delegate show/hide to Provider
308-
if (uniqueContext) {
309-
if (nextOpen && targetEle) {
310-
uniqueContext.show(targetEle, delay);
311-
} else {
312-
uniqueContext.hide(targetEle, delay);
313-
}
314-
return;
315-
}
316-
307+
const internalTriggerOpen = useEvent((nextOpen: boolean) => {
317308
setMergedOpen(nextOpen);
318309

319310
// Enter or Pointer will both trigger open state change
@@ -330,32 +321,24 @@ export function generateTrigger(
330321
});
331322

332323
// Trigger for delay
333-
const delayRef = React.useRef<ReturnType<typeof setTimeout>>(null);
334-
335-
const clearDelay = () => {
336-
clearTimeout(delayRef.current);
337-
};
324+
const delayInvoke = useDelay();
338325

339326
const triggerOpen = (nextOpen: boolean, delay = 0) => {
340327
// If UniqueContext exists, pass delay to Provider instead of handling it internally
341328
if (uniqueContext) {
342-
internalTriggerOpen(nextOpen, delay);
329+
if (nextOpen && targetEle) {
330+
uniqueContext.show(targetEle, delay);
331+
} else {
332+
uniqueContext.hide(targetEle, delay);
333+
}
343334
return;
344335
}
345336

346-
clearDelay();
347-
348-
if (delay === 0) {
337+
delayInvoke(() => {
349338
internalTriggerOpen(nextOpen);
350-
} else {
351-
delayRef.current = setTimeout(() => {
352-
internalTriggerOpen(nextOpen);
353-
}, delay * 1000);
354-
}
339+
}, delay);
355340
};
356341

357-
React.useEffect(() => clearDelay, []);
358-
359342
// ========================== Motion ============================
360343
const [inMotion, setInMotion] = React.useState(false);
361344

0 commit comments

Comments
 (0)