How can I detect if the shift key is currently pressed down? I have a text input, and when the user presses the enter key I only want to submit the form if they are not currently pressing the enter key (same form functionality as Facebook Messenger on desktop).
Here is my text input:
<TextInput
style={styles.input}
placeholder={'Enter message'}
onKeyPress={this.handleKeyPress}
/>
And here is the handler:
handleMessageInputKeyPress(e) {
if(e.nativeEvent.key == "Enter"){
// Now check if the SHIFT key is currently pressed or not...
}
}
How can I detect if the shift key is currently pressed down? I have a text input, and when the user presses the enter key I only want to submit the form if they are not currently pressing the enter key (same form functionality as Facebook Messenger on desktop).
Here is my text input:
<TextInput
style={styles.input}
placeholder={'Enter message'}
onKeyPress={this.handleKeyPress}
/>
And here is the handler:
handleMessageInputKeyPress(e) {
if(e.nativeEvent.key == "Enter"){
// Now check if the SHIFT key is currently pressed or not...
}
}
Share
Improve this question
edited Jan 14, 2017 at 8:42
Leopold Joy
asked Jan 14, 2017 at 8:33
Leopold JoyLeopold Joy
4,6604 gold badges29 silver badges38 bronze badges
6
-
1
e.nativeEvent.shiftKey
? – Teemu Commented Jan 14, 2017 at 8:36 -
@Teemu I get
undefined
when I addconsole.log(e.nativeEvent.shiftKey);
inside theif
statement. – Leopold Joy Commented Jan 14, 2017 at 8:41 -
?? Then simply check
'Shift'
instead of'Enter'
? Ah... Shift doesn't firekeypress
... – Teemu Commented Jan 14, 2017 at 8:42 -
@Teemu But I want to check if the
Shift
key is pressed at the same time as theEnter
key. How can I do that? – Leopold Joy Commented Jan 14, 2017 at 8:44 -
1
You need another event, like
keydown
orkeyup
,keypress
is not fired by SHIFT, though.shiftKey
still should be defined. – Teemu Commented Jan 14, 2017 at 8:45
3 Answers
Reset to default 6You can use event listeners to detect any time a key is pressed (or unpressed), then filter the results for the key you want to use as a conditional. Here's an example using hooks:
const [shiftHeld, setShiftHeld] = useState(false);
function downHandler({key}) {
if (key === 'Shift') {
setShiftHeld(true);
}
}
function upHandler({key}) {
if (key === 'Shift') {
setShiftHeld(false);
}
}
useEffect(() => {
window.addEventListener('keydown', downHandler);
window.addEventListener('keyup', upHandler);
return () => {
window.removeEventListener('keydown', downHandler);
window.removeEventListener('keyup', upHandler);
};
}, []);
This will change the state to true or false depending on whether the shift key is held down or not. Then you can plug that value in anywhere you need it.
Tip: You can use this format to listen for any other key. I had a hard time finding documentation on what the keys are called. If you have trouble finding the key name, implement this code then console log key
just before the if
statement in the downHandler
.
Also, make sure you leave the listeners in a useEffect
, otherwise you'll get data leaks.
For those who are still looking for the solution:
It seems the event
received by the callback onKeyPress
has the following properties:
It's nice to see it also has ctrlKey
& altKey
.
So the solution would be:
<TextInput
onKeyPress={event => {
if (event.shiftKey && event.key === "Enter"){
// ...
}
}} />
create a hook like this
import React, {useEffect, useState} from "react";
const useKeyPress = (keyMap, callbackMap) => {
const [keyPressed, setKeyPressed] = useState(new Set());
const downHandler = (event) => {
event.preventDefault();
const { key, altKey, shiftKey, ctrlKey } = event;
const modifiers = [];
if (altKey) modifiers.push('alt');
if (shiftKey) modifiers.push('shift');
if (ctrlKey) modifiers.push('ctrl');
// Generate all possible binations of modifiers and key
const binations = [ [key.toLowerCase()],
[modifiers.join('+'), key.toLowerCase()],
[modifiers.reverse().join('+'), key.toLowerCase()]
];
for (const bination of binations) {
const id = keyMap[bination.join('+')];
const callback = callbackMap[id];
if (callback) {
const newKeyPressed = new Set(keyPressed);
newKeyPressed.add(bination.join('+'));
setKeyPressed(newKeyPressed);
callback();
break;
}
}
};
const upHandler = (event) => {
event.preventDefault();
const { key, altKey, shiftKey, ctrlKey } = event;
const modifiers = [];
if (altKey) modifiers.push('alt');
if (shiftKey) modifiers.push('shift');
if (ctrlKey) modifiers.push('ctrl');
// Generate all possible binations of modifiers and key
const binations = [ [key.toLowerCase()],
[modifiers.join('+'), key.toLowerCase()],
[modifiers.reverse().join('+'), key.toLowerCase()]
];
for (const bination of binations) {
const id = keyMap[bination.join('+')];
const callback = callbackMap[id];
if (callback) {
const newKeyPressed = new Set(keyPressed);
newKeyPressed.delete(bination.join('+'));
setKeyPressed(newKeyPressed);
break;
}
}
};
useEffect(() => {
window.addEventListener('keydown', downHandler);
window.addEventListener('keyup', upHandler);
return () => {
window.removeEventListener('keydown', downHandler);
window.removeEventListener('keyup', upHandler);
};
});
return keyPressed;
};
export default useKeyPress;
Then use can use it like this in your other ponents;
// Keyboard mappings
const keyMap = {
'ctrl+shift+p': 'preview',
};
const callbackMap = {
'preview': () => setShowModal(prevModalVisible => !prevModalVisible),
};
useKeyPress(keyMap, callbackMap);
With technique you can map any three key binations of your liking