Hone logo
Hone
Problems

React useKeyPress Hook Implementation

This challenge focuses on creating a custom React hook, useKeyPress, that allows components to easily track whether a specific key is currently being pressed. This is a common requirement for building interactive user interfaces, such as keyboard shortcuts, game controls, or custom input handling.

Problem Description

Your task is to implement a custom React hook named useKeyPress that accepts a target key code (or key name) as an argument and returns a boolean value indicating whether that key is currently pressed down.

Key Requirements:

  1. Hook Signature: The hook should have the signature useKeyPress(targetKey: string): boolean.
    • targetKey: A string representing the key to track. This could be a keyCode (e.g., 'Enter' for key code 13) or a key name string (e.g., 'a', 'ArrowUp').
    • Return Value: A boolean, true if the targetKey is currently pressed, false otherwise.
  2. Event Listeners: The hook must correctly attach and detach keydown and keyup event listeners to the window object.
  3. State Management: The hook should manage an internal state to keep track of whether the targetKey is pressed.
  4. Cleanup: Ensure that event listeners are removed when the component using the hook unmounts to prevent memory leaks.

Expected Behavior:

  • When a component mounts and uses useKeyPress for a specific key, the returned boolean should be false initially.
  • When the user presses the targetKey, the hook should return true.
  • When the user releases the targetKey, the hook should return false.
  • Pressing other keys should not affect the state for the targetKey.

Edge Cases to Consider:

  • Case Sensitivity: How will you handle key names? For simplicity, you can assume case-insensitive matching for key names if needed, or specify that the targetKey should match the KeyboardEvent.key property directly.
  • Modifier Keys: While not strictly required for the initial implementation, consider how modifier keys (Shift, Ctrl, Alt) might interact if you were to extend this hook in the future.
  • Browser Compatibility: Ensure your solution is generally compatible with modern browsers.

Examples

Example 1: Tracking the 'a' key

import React, { useState } from 'react';
import { useKeyPress } from './useKeyPress'; // Assuming your hook is in this file

function KeyTracker() {
  const isAPressed = useKeyPress('a');

  return (
    <div>
      Press the 'a' key!
      <p>Is 'a' pressed? {isAPressed ? 'Yes' : 'No'}</p>
    </div>
  );
}

Input: User presses and holds the 'a' key. Output: The text "Is 'a' pressed? Yes" will be displayed. When the key is released, it will change to "Is 'a' pressed? No".

Explanation: The useKeyPress hook listens for keydown and keyup events. When 'a' is pressed, isAPressed becomes true. When 'a' is released, isAPressed becomes false.

Example 2: Tracking the 'Enter' key

import React, { useState } from 'react';
import { useKeyPress } from './useKeyPress';

function EnterButton() {
  const isEnterPressed = useKeyPress('Enter'); // Or potentially use a key code if preferred

  return (
    <div>
      <button>Click Me</button>
      {isEnterPressed && <p>Enter key is currently held down!</p>}
    </div>
  );
}

Input: User presses and holds the 'Enter' key while the EnterButton component is mounted. Output: The text "Enter key is currently held down!" will appear. Explanation: The hook returns true for isEnterPressed as long as the 'Enter' key is down, triggering the conditional rendering of the paragraph.

Constraints

  • The targetKey string should generally correspond to the KeyboardEvent.key property. For common keys like 'Enter', 'Escape', 'ArrowUp', etc., this is straightforward. For letter keys, it would be the lowercase letter (e.g., 'a', 'b').
  • The hook should be efficient and avoid unnecessary re-renders.
  • The solution must be written in TypeScript.

Notes

  • Consider using KeyboardEvent.key for a more modern and consistent approach to identifying keys compared to keyCode (which is deprecated).
  • The useEffect hook will be crucial for managing the side effects of adding and removing event listeners.
  • Think about how to efficiently update the state within the event handlers.
Loading editor...
typescript