Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

133
Views
Increase and decrease the number using addEventListener keydown in React

I wrote a program that adds or subtracts a unit to count by pressing the up and down keys on the keyboard. The problem is that the program does not work properly. When you press the key, look at the console, which runs several times, while each time you press the key, it only has to run once. This is a problem that crashes after pressing the up or down buttons a few times, please help

import React, { useState } from "react";

export default function Example() {
  const [count, setCount] = useState(0);

  document.addEventListener("keydown", function (e) {
    switch (e.keyCode) {
      case 38:
        setCount(count + 1);
        console.log(count);
        break;
      case 40:
        setCount(count - 1);
        console.log(count);
        break;
    }
  });
  return (
    <div>
      <p>You clicked {count} times</p>
    </div>
  );
}
about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

You are adding an event handler every time the component is rendered. The component is re-rendered whenever the state changes. It's an exponential loop, hence your application "crashes".

  • Use useEffect to attach the event listener once the component is mounted and remove it again once the component is unmounted.
  • Provide a callback to setCount to access the current count.
export default function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const keyDownCallback = function (e) {
      switch (e.keyCode) {
        case 38:
          setCount((count) => count + 1);
          break;
        case 40:
          setCount((count) => count - 1);
          break;
      }
    };

    document.addEventListener("keydown", keyDownCallback);

    return () => document.removeEventListener("keydown", keyDownCallback);
  }, []);

  return (
    <div>
      <p>You clicked {count} times</p>
    </div>
  );
}

See demo

Documentation

  • useEffect
about 4 years ago · Juan Pablo Isaza Report

0

Well each time your component re-renders, it attaches that event listener again and again and calls setCount too many times and re-renders component too many times. Therefore your program falls into infinite loop. I think you should try useEffect and useLayoutEffect hooks.

Edit

import React from "react";

export default function App() {
  const [count, setCount] = React.useState(0);

  const handleUpdateCount = React.useCallback(
    (value) => setCount((prevCount) => prevCount + value),
    [setCount]
  );

  React.useEffect(() => {
    const keyDownCallback = (e) => {
      switch (e.keyCode) {
        case 38:
          handleUpdateCount(1);
          break;
        case 40:
          handleUpdateCount(-1);
          break;
        default:
          console.log("default");
      }
    };

    document.addEventListener("keydown", keyDownCallback);

    return () => document.removeEventListener("keydown", keyDownCallback);
  }, [handleUpdateCount]);

  return (
    <div>
      <p>You clicked {count} times</p>
    </div>
  );
}

In these way, we prevent from extra re-renders.

And about useLayoutEffect, this hook runs given callback after all DOM mutations, But according to official React documentation, We should tend to use useEffect as possible. https://reactjs.org/docs/hooks-reference.html

about 4 years ago · Juan Pablo Isaza Report

0

You have to put document.addEventListener in an useEffect or it will add an event listener each time component re-render

useEffect(() => {
   document.addEventListener("keydown", function (e) {
    switch (e.keyCode) {
      case 38:
        setCount(count + 1);
        console.log(count);
        break;
      case 40:
        setCount(count - 1);
        console.log(count);
        break;
    }
  });
}, [])
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!