Itay Zuker
Itay Zuker

Reputation: 31

Why is the console.log() printing multiple times with all the previous values?

When I click the plus button, the number state updates with +1 as expected. But if I click the plus button 5 times (Or any other number of times). when I try to print the number value in the console with the keydown event, I get five prints of 0 to 5 (Or as many times as I previously clicked the plus button). Why is this happening? And how can I get just one print with the current (updated) value?

This is the screenshot

    let [number, setNumber] = useState(0)

    function plus() {setNumber(number += 1)}

    function ptintNumber() {
        console.log(number)
    }

    document.addEventListener('keydown', ptintNumber)

    return <div>
        <h1>{number}</h1>
        <button onClick={plus}>+</button>
    </div>   

Upvotes: 1

Views: 5388

Answers (3)

codemonkey
codemonkey

Reputation: 7915

To answer your specific question: the reason this happens is because you tie an event listened to your document on every render, which happens each time you click the Plus button. So every keydown is calling your ptintNumber exactly as many time as you clicked the Plus button.

Solution: Put your even listener into useEffect like so:

import React from "react";
import "./styles.css";

export default function App() {
  let [number, setNumber] = React.useState(0);
  const number_ref = React.useRef();
  number_ref.current = number;

  function plus() {
    setNumber((number += 1));
  }

  function ptintNumber() {
    console.log(number_ref.current);
  }

  React.useEffect(() => {
    document.addEventListener("keydown", ptintNumber);
  }, []);

  return (
    <div className="App">
      <h1>{number}</h1>
      <button onClick={plus}>+</button>
    </div>
  );
}

Sandbox: https://codesandbox.io/s/wizardly-antonelli-vix6q?file=/src/App.js

Upvotes: 2

Victor Jozwicki
Victor Jozwicki

Reputation: 720

If you wish to see the value, you need to use a useEffect hook that will react to the number change. The value you could be outputting with your method might not be the right value

import React, { useEffect, useState } from "react";

export default function App() {
  let [number, setNumber] = useState(0);
  function plus() {
    setNumber((previousNumber) => previousNumber + 1);
  }

  useEffect(() => {
    console.log(number);
  }, [number]);

  return (
    <div className="App">
      <h1>{number}</h1>
      <button onClick={plus}>+</button>
    </div>
  );
}

You should also base your new value on the previous one

Codesandbox example

Upvotes: 1

Hemant
Hemant

Reputation: 1166

You can use onKeyDown instead of addEventListener

function ButtonComp() {
    let [number, setNumber] = useState(0);
    // document.addEventListener("keydown", ptintNumber);

    return (
        <div>
            <h1>{number}</h1>
            <button onClick={() => setNumber(number+1)} onKeyDown={() => {console.log(number)}}>+</button>
        </div>
    );
}

Upvotes: 1

Related Questions