UNPKG

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