I can get the onKeyPress event to fire from the canvas
<canvas
id='canvas'
ref={canvasRef}
className='canvas'
tabIndex={0}
onKeyPress={(e: React.KeyboardEvent) => setKeyDown(e)}
/>
But the setKeyDown function thst recieves the event doesnt seem to fire when I press delete while other keys do log values, I want to know if the delete key was pressed.
const setKeyDown = (event: React.KeyboardEvent<Element>) => {
console.log(event.keyCode);
console.log(event.key);
};
I have tried using any as the type but I get the same results
onKeyPress doesn't capture the delete key. To capture delete key presses use onKeyDown event.
onKeyDown={(e: React.KeyboardEvent) => setKeyDown(e)}
You need to capture onKeyDown event
your event handler be like
onDelete = (e) => {
if (e.keyCode === 46) {
alert(e.keyCode);
}
};
Keycode for delete key is 46
Related
I have a handleBackspace function that does something if backspace is being pressed.
I tried this:
const handleBackspace = (e) => {
if(e.keyCode === 8) {
console.log('1')
}
}
//
<input onKeyPress={handleBackspace}>
But that doesn't work. (I tried it with keyCode 13 [enter] and it worked. But keyCode 8 [backspace] doesn't work) Can someone show me a solution?
As can be read here, onKeyPress only receives charCode instead of keyCode.
This gives us three possible answers to this issue:
Either change the event to onKeyDown
Change the listener to check e.charCode
Use e.which, which will work for both onKeyPress and onKeyDown.
onKeyDown detects keyCode events.
Try changing it to onKeyDown event.
Sandbox: https://codesandbox.io/s/react-basic-class-component-kzv2k?file=/src/index.js
handleBackspace = e => {
if (e.keyCode === 8) {
console.log("1");
}
};
render() {
return <input onKeyDown={this.handleBackspace} />;
}
I'm working on a login function right now. I put my enterKey function in the input, and my aim is to call the login function when the user press the enter key. It works fine if there's nothing in the input area, however, I find that if I have some characters in the input text area, the function will be called multiple times and give multiple error messages.
For example, if I have N characters in the input, I will receive (N+1) error messages after press the enter key.
Here is my code:
enterKeyPress() {
window.addEventListener("keypress", e => {
if (e.keyCode === 13) {
console.log('enter key pressed!'); // I will receive this msg (N+1) times when there're N characters in the input text area
e.preventDefault();
this.loginUser(); // this is the login function I want to call after press enter key, but just once per press
}
});
}
render() {
return(
<Input
type="password"
placeholder="Password"
onChange={e =>
this.setState({ password: e.target.value })
}
onKeyPress={this.enterKeyPress()}
/>
);
}
Can anyone help me with this?
Event listeners aren't necessary in this case.
First thing, adjust enterKeyPress to not create an event listener. If you haven't bound the function in your constructor, then you can convert enterKeyPress to an arrow function:
enterKeyPress = (e) => {
if (e.keyCode === 13) {
console.log('enter key pressed!');
e.preventDefault();
this.loginUser();
});
}
Converting enterKeyPress to an arrow function is one way to scope the function to the component. Another option is binding the function in your constructor or in your render function, which is well documented elsewhere. If you've already bound the function in your constructor (you haven't included it here), then you can ignore that part.
Second, adjust your onKeyPress prop to pass the function rather than calling it:
<Input
type="password"
placeholder="Password"
onChange={e =>
this.setState({ password: e.target.value })
}
onKeyPress={this.enterKeyPress}
/>
It's also worth noting that there's another general JavaScript mistake here: using an anonymous callback function in your event listener. By using an anonymous function, you're enabling the same function to be added multiple times, since a different function reference is generated each time. This also means that you won't be able to remove it later, since you'll require the function reference to do so.
Again, you don't need an event listener here, but if you did, you should probably define the callback in the component scope, so that you can remove it at some later point. A common pattern for using event listeners is as follows:
handleKeyPress = (e) => {
if (e.keyCode === 13) {
console.log('enter key pressed!');
e.preventDefault();
this.loginUser();
});
}
componentDidMount() {
window.addEventListener("keypress", this.handleKeyPress);
}
componentWillUnmount() {
window.removeEventListener("keypress", this.handleKeyPress);
}
From some quick Googling, I think this might do what you need:
enterKeyPress(e) {
if (e.keyCode === 13) {
console.log('enter key pressed!'); // I will receive this msg (N+1) times when there're N characters in the input text area
e.preventDefault();
this.loginUser(); // this is the login function I want to call after press enter key, but just once per press
});
}
render() {
return(
<Input
type="password"
placeholder="Password"
onChange={e =>
this.setState({ password: e.target.value })
}
onKeyPress={this.enterKeyPress}
/>
);
}
onKeyPress already does what the event listener you're trying to add does, so just pass it the keypress event directly instead.
Like #Ronnie has pointed out in the comments, you are adding a new event listener every time the onKeyPress function is triggered on the component, which causes the problems. Since onKeyPress event already passes the event as an argument (similar to onClick event), you can access the keyCode from there.
You can change your enterKeyPress function to the following:
enterKeyPress(e) {
if (e.keyCode === 13) {
console.log('enter key pressed!');
e.preventDefault();
this.loginUser();
}
}
I have a React Modal that opens and closes via a handler function.
I'd like to call that function with either a click event or with the use of the esc key for accessibility proposes.
How could I track both events at the same time?
So far I got the esc event as:
handleCloseModal = event => {
if (event.keyCode === 27) {
this.setState({ modal: false })
}
}
But then I lose the click functionality on
<Modal
onClick={handleCloseModal}
role="button" tabIndex={0}
onKeyDown={handleCloseModal}
/>
How should I go about this?
One possible solution can be: Create a separate function to close the Modal. Use that function for onClick and call it when esc key pressed.
Like this:
<Modal
onClick={handleCloseModal}
role="button" tabIndex={0}
onKeyDown={handleKeyDown}
/>
handleKeyDown = event => {
if (event.keyCode === 27) {
handleCloseModal()
}
}
handleCloseModal = () => this.setState({ modal: false })
If I understand correctly, you're wanting to reuse the same close event handler for both click and keydown event types. One way to distinguish between these two event types would be to detect the event object's type via instanceof as follows:
handleCloseModal = event => {
// if event is mouse event, handle it accordingly
if(event instanceof MouseEvent) {
// if mouse click detected hide the modal
this.setState({ modal: false })
}
// if event is keyboard event, handle it accordingly
else if(event instanceof KeyboardEvent) {
// if escape key pressed for keyboard event then hide the modal
if (event.keyCode === 27) {
this.setState({ modal: false })
}
}
}
let's say I have a function that gets executed on key press that looks like something like this. I want to have special case for when Enter is pressed otherwise I want even to propogate/bubble up to the browser. Therefore, if any other key is pressed this i.e up or down arrows they should work.
onAutosuggestInputKeyDown = event => {
if (event.key === 'Enter') {
this.onCustomSuggestionCreate(event)
} else {
// keep propgating the event
}
}
getAutosuggestInputProps = () => {
return {
inputProps: {
onBlur: this.onCustomSuggestionCreate,
onKeyDown: this.onAutosuggestInputKeyDown,
},
}
}
<ReactAutoSuggest textFieldProps={this.getAutosuggestInputProps()}/>
If I understand your situation correctly, then even propagation should occour by default (depending on the type of element that fired the event).
You would however, likely want to use stopPropagation() in the case of the enter key being pressed to prevent the propagation of that event, which would be achieved by the following update to your onAutosuggestInputKeyDown method:
onAutosuggestInputKeyDown = event => {
if (event.key === 'Enter') {
// Prevent this event from propagating if enter key pressed
event.stopPropagation()
this.onCustomSuggestionCreate(event)
}
// If stopPropagation() not called on event, the event will propagate
// if it has the ability to do so (ie from the element dispatching the
// event)
}
I want to run a method whenever the ESC button gets clicked. In the onkeypress Event documentation I read that i will have to use keydown
Note: The onkeypress event is not fired for all keys (e.g. ALT, CTRL, SHIFT, ESC) in all browsers. To detect only whether the user has pressed a key, use the onkeydown event instead, because it works for all keys.
I managed to write a working example:
document.onkeydown = function (e) {
if (document.getElementById("fullscreen") !== null) {
var key = e.which || e.keyCode;
if (key === 27) {
alert(1);
}
}
}
<div id="fullscreen">test</div>
The event listeners in our project have a different pattern, so I tried rewrite it in the same pattern but the code isn't reacting on the key press.
document.getElementById("fullscreen").addEventListener("keydown",
function (e) {
var key = e.which || e.keyCode;
if (key === 27) {
alert(1);
}
});
<div id="fullscreen">test</div>
Why isn't the second code snippet reacting on the key press like the first snippet?