Giter Site home page Giter Site logo

use-keydown's Introduction

use-keydown

NPM version Actions Status PR Welcome

React hook for listening to custom keydown events.

Introduction

This hook optimizes keyboard event handling by only initializing a single event listener for each target used, resulting in a more streamlined and efficient process.

This library is also SSR safe, and only runs on the client.

Installation

Install this package with npm.

npm i @buildinams/use-keydown

Usage

To listen to a single key:

import useKeydown from "@buildinams/use-keydown";

useKeydown("Escape", () => {}); // Do something on "Escape"...

To listen to key modifiers:

import useKeydown from "@buildinams/use-keydown";

useKeydown("KeyG", (event: KeyboardEvent) => {
  if (event.ctrlKey) // Do something on "Ctrl + G"...
});

To listen to multiple keys:

import useKeydown from "@buildinams/use-keydown";

useKeydown(["KeyA", "KeyG"], () => {}); // Do something on "A" or "G"...

Note: When using multiple keys, the callback will be called if any of the defined keys are pressed.

Using Custom Targets

By default, the hook will listen to the window object. You can however listen to any custom target by passing it as target within the optional config object. This accepts any object that extends EventTarget, such as; document or HTMLElement. For example:

import useKeydown from "@buildinams/use-keydown";

const elementRef = useRef<HTMLDivElement>(null);
useKeydown("Enter", () => {}, { target: elementRef });

Conditionally Listening to Events

You can conditionally listen to events by passing a isEnabled prop the config object. This accepts a boolean value, and will only listen to events if the value is true (default). For example:

import useKeydown from "@buildinams/use-keydown";

const [isEnabled, setIsEnabled] = useState(false);

useKeydown("Enter", () => {}, { isEnabled });

Requirements

This library requires a minimum React version of 17.0.0.

Requests and Contributing

Found an issue? Want a new feature? Get involved! Please contribute using our guideline here.

use-keydown's People

Contributors

dependabot[bot] avatar paulomfj avatar

Stargazers

 avatar

use-keydown's Issues

[FEATURE REQUEST] Support passing multiple keys

What is the problem you're trying to solve?

In the YOMI project we have a Slider primitive that reacts to ArrowLeft and ArrowRight events, and should almost do the same thing based on the key that was pressed.

This looks something like this:

useKeyPress(['ArrowLeft', 'ArrowRight'], (e) => {
    // Do something
})

In our implementation we have a check for the key and act on that. While arguably it is better to separate these out into two hooks, e.g.:

useKeyPress('ArrowLeft', (e) => {
 // handle arrow left
})

useKeyPress('ArrowRight', (e) => {
  // handle arrow right
}) 

I can see it happen that we want to fire something when a key event is fired on different keys. Silly example below, but it illustrates the point

Let's say I have a function that should fire when a vowel key is pressed:

const handleVowelKeyDown = () => {
  throw new Error('You are only allowed to press consonants')
}

If I had to do that using the current implementation, I would have to do this:

useKeyDown('KeyA', handleVowelKeyDown)
useKeyDown('KeyE', handleVowelKeyDown)
useKeyDown('KeyU', handleVowelKeyDown)
useKeyDown('KeyI', handleVowelKeyDown)
useKeyDown('KeyO', handleVowelKeyDown)

What solution would you like to see?

It could be nice to support passing an array of keys that register the callback for each of these events.

useKeyDown(['KeyA', 'KeyE', 'KeyU', 'KeyI', 'KeyO'], handleVowelKeyDown)

To be backwards compatible and for ease of use, we could allow to still pass a string if you only need one key. So, the below examples would all work:

useKeyDown('Escape', handleEscapeKeyDown)
useKeyDown(['KeyA', 'KeyE', 'KeyU', 'KeyI', 'KeyO'], handleVowelKeyDown)

Closing thoughts

We could also extract this out in a separate hook, but it feels fitting to be implemented in this (and the use-keyup) package

[FEATURE REQUEST] Support custom event target

What is the problem you're trying to solve?

In the YOMI project we have a Slider primitive that reacts to ArrowLeft and ArrowRight events, but we only need it to listen if any element in the Slider component is focussed.

We can do that by listening on the actual element itself, instead of the window.

So, our current implementation is something like this:

useKeyPress('ArrowLeft', (e) => {
    // I only listen on the ref element
  }, 
  { 
    listenOn: ref 
  }
)

What solution would you like to see?

We can arguably solve this issue by actively checking if any element in the slider is the document.activeElement, but that just adds overhead. I think it could be a great benefit to be able to pass a target as a config, something like:

import useKeyDown from '@buildinams/use-keydown'

// ...

const someElementRef = useRef()

useKeyDown('ArrowLeft', (e) => {
    // do something
  },
  {
     target: someElementRef
   }
)

We could default the config target to window and allow the target config to either receive a ref object or a document node, e.g, these next scenarios would all work:

useKeyDown('ArrowLeft', e => {}, { target: document })
useKeyDown('ArrowLeft', e => {}, { target: { current: document })
const ref = useRef()
useKeyDown('ArrowLeft', e => {}, { target: ref })

Closing thoughts

I understand that it is a niche usecase with a low priority, and I might not see the drawbacks too clearly, but I found it a valuable extension to this hook.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.