UNPKG

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