UNPKG

2.6 kBJavaScriptView Raw
1function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
3import { useRef } from 'react';
4import useMounted from './useMounted';
5import useEventCallback from './useEventCallback';
6
7var isSyntheticEvent = function isSyntheticEvent(event) {
8 return typeof event.persist === 'function';
9};
10
11/**
12 * Creates a event handler function throttled by `requestAnimationFrame` that
13 * returns the **most recent** event. Useful for noisy events that update react state.
14 *
15 * ```tsx
16 * function Component() {
17 * const [position, setPosition] = useState();
18 * const handleMove = useThrottledEventHandler<React.PointerEvent>(
19 * (event) => {
20 * setPosition({
21 * top: event.clientX,
22 * left: event.clientY,
23 * })
24 * }
25 * )
26 *
27 * return (
28 * <div onPointerMove={handleMove}>
29 * <div style={position} />
30 * </div>
31 * );
32 * }
33 * ```
34 *
35 * @param handler An event handler function
36 * @typeParam TEvent The event object passed to the handler function
37 * @returns The event handler with a `clear` method attached for clearing any in-flight handler calls
38 *
39 */
40export default function useThrottledEventHandler(handler) {
41 var isMounted = useMounted();
42 var eventHandler = useEventCallback(handler);
43 var nextEventInfoRef = useRef({
44 event: null,
45 handle: null
46 });
47
48 var clear = function clear() {
49 cancelAnimationFrame(nextEventInfoRef.current.handle);
50 nextEventInfoRef.current.handle = null;
51 };
52
53 var handlePointerMoveAnimation = function handlePointerMoveAnimation() {
54 var next = nextEventInfoRef.current;
55
56 if (next.handle && next.event) {
57 if (isMounted()) {
58 next.handle = null;
59 eventHandler(next.event);
60 }
61 }
62
63 next.event = null;
64 };
65
66 var throttledHandler = function throttledHandler(event) {
67 if (!isMounted()) return;
68
69 if (isSyntheticEvent(event)) {
70 event.persist();
71 } // Special handling for a React.Konva event which reuses the
72 // event object as it bubbles, setting target
73 else if ('evt' in event) {
74 event = _extends({}, event);
75 }
76
77 nextEventInfoRef.current.event = event;
78
79 if (!nextEventInfoRef.current.handle) {
80 nextEventInfoRef.current.handle = requestAnimationFrame(handlePointerMoveAnimation);
81 }
82 };
83
84 throttledHandler.clear = clear;
85 return throttledHandler;
86}
\No newline at end of file