React: issue with keydown event listener

Hi everyone,

I have two buttons which have an onClick event listener and everything is working fine. However, I also want to add keydown events referencing to the same functions as onClick in buttons but for some reason the functions are not executed when I press the key.

I was trying to look for an error and used console.log to log some text every time the relevant keys are pressed - the text is logged into console but the functions still don’t work.
Can someone please help me understand why?

useEffect(() => {

      fetchRandomQuestion();
    // adding event listener
    window.addEventListener('keydown', handleKeyDown);
      // clean up
      return () => {
          window.removeEventListener('keydown', handleKeyDown);
      };
  },[]);

// function referenced to onClick event of one of the buttons - working fine:
const handleNewQuestion = () => {
   
    setPrevQuestion([...prevQuestion, question]);
    setPrevAnswer([... prevAnswer,answer]);
     // ... rest of the code //

    fetchRandomQuestion();
  };

// function referenced to onClick event of another buttons - working fine:
const handlePrevQuestion = () => {
    if (prevQuestion.length === 0 && prevAnswer.length === 0) return
    else {
      setQuestion(prevQuestion.pop());
      setAnswer(prevAnswer.pop());
     // ... //
    }

  }

 // keydown events
 const handleKeyDown = (e) => {
    if (e.key === "ArrowLeft") {
      handlePrevQuestion();    // this has no effect
   console.log('back')     // this is logged in the console
    }
    else if (e.key === "ArrowRight") {
      handleNewQuestion();    // this has no effect
   console.log('next')     // this is logged in the console
    }
}

return (
   <div>
         <Button onClick={handlePrevQuestion}>back</Button>
         <Button onClick={handleNewQuestion}>next</Button>
  </div>
)
};

Why is the dependency array of useEffect empty?

Because I only want to run useEffect on the first render of the component.

And where does handlePrevQuestion gets prevQuestion from?

const [prevQuestion, setPrevQuestion] = useState([]);

from the state which is an array as above.

And what happens if you move keydown listener into separate useEffect and add handleKeyDown to the dependency array?

1 Like

handleKeyDown is a function. Can I add it to the dependency array? When I tried to add another useEffect as proposed, I got the below error:
Uncaught ReferenceError: Cannot access 'handleKeyDown' before initialization

Yes you can.
The idea is that your handler is working with empty values from initial render and it’s not updated because it is only declared on the initial render, when there is no data yet.

It would be better if you’d post your code on codesanbox or codepen.

1 Like