React callbackRef.current is not a function

1.3k views Asked by At

I'm working on a React app that uses an npm library (react-dropzone) which unfortunately does not have accessibility built-in.

What I'm trying to do is create a keypress event that will recognize when the "ENTER" key is pressed without manually clicking on the button.

import React, { useEffect, useRef } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function useKey(key, cb) {
  const callbackRef = useRef(cb);

  useEffect(() => {
    callbackRef.current = cb;
  });

  useEffect(() => {
    function handle(event) {
      if (event.code === key) {
        callbackRef.current(event);
      }
    }
    document.addEventListener("keypress", handle);
    return () => document.removeEventListener("keypress", handle);
  }, [key]);
}

function App() {
  function handleEnter() {
    console.log("Enter key is pressed");
  }

  useKey("Enter", handleEnter());

  return (
    <div className="App">
      <button onClick={() => handleEnter()}> Press Enter </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

In my demo https://codesandbox.io/s/lingering-sound-yptbk, I've placed my handleEnter function in my onClick event. I can press the enter key but the following error occurs:

callbackRef.current is not a function
useEffect(() => {
  14 |   function handle(event) {
  15 |     if (event.code === key) {
> 16 |       callbackRef.current(event);
     |                  ^
  17 |     }
  18 |   }

I've tried the non-React accepted solution here on SO: dropzone.js Accessibility but could not get it to work. Since I'm not familiar with keypress events using React Hooks, I'm not sure where to go from here. What would be the best way to implement this?

1

There are 1 answers

1
norbitrial On

You need to pass a callback instead of calling the function once pass to useKey as:

useKey("Enter", handleEnter);

See the difference when changed from handleEnter() to handleEnter.

In your case you are passing as a parameter the return value of the executed function, in the second case what I'm suggesting above it's a callback instead.