-
Notifications
You must be signed in to change notification settings - Fork 800
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Only register a single set of event listeners for the entire document
when tracking whether a keyboard or a mouse is being used.
- Loading branch information
1 parent
74b182b
commit 3cf4f2d
Showing
2 changed files
with
54 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import * as React from 'react'; | ||
|
||
let isUsingKeyboard = false; | ||
let isUsingKeyboardSubscriberCount = 0; | ||
|
||
function handleKeydown() { | ||
isUsingKeyboard = true; | ||
} | ||
|
||
function handlePointer() { | ||
isUsingKeyboard = false; | ||
} | ||
|
||
function getIsUsingKeyboard() { | ||
return isUsingKeyboard; | ||
} | ||
|
||
function subscribeShared() { | ||
if (isUsingKeyboardSubscriberCount++ === 0) { | ||
// Capture phase ensures we set the boolean before any side effects execute | ||
// in response to the key or pointer event as they might depend on this value. | ||
document.addEventListener('keydown', handleKeydown, { capture: true }); | ||
document.addEventListener('pointerdown', handlePointer, { capture: true }); | ||
document.addEventListener('pointermove', handlePointer, { capture: true }); | ||
} | ||
} | ||
|
||
function unsubscribeShared() { | ||
if (--isUsingKeyboardSubscriberCount === 0) { | ||
document.removeEventListener('keydown', handleKeydown, { capture: true }); | ||
document.removeEventListener('pointerdown', handlePointer, { capture: true }); | ||
document.removeEventListener('pointermove', handlePointer, { capture: true }); | ||
} | ||
} | ||
|
||
/** | ||
* Starts tracking whether the user is using a keyboard or a mouse. | ||
* This implementation keeps track of how many subscribers it has and makes sure | ||
* only one set of listeners is attached to the document to improve performance and | ||
* prevent memory leaks. | ||
*/ | ||
export function useIsUsingKeyboard() { | ||
React.useEffect(() => { | ||
subscribeShared(); | ||
return unsubscribeShared; | ||
}, []); | ||
|
||
return getIsUsingKeyboard; | ||
} |