React keypress event taking only initial state values and not updated values

I am creating a React application in which I have one state called input which is taking input from user . I want that when I press enter key , alert should display the input which is getting set in state . However, on clicking enter key , only default value set in input state is getting displayed .

But when I click on a button (which I have created to display the input in alert), then the input displayed in alert is correct .

Please see the code snippet below for reference .

import React, { useEffect, useRef, useState } from 'react';

export default function ShowAlertExample() {

  const [input, setInput ] = useState('1');
  const handleInputChange = (e) => {
    setInput(e.target.value);
  }

  const handleShowAlert = () => {
    alert(input);
  }

  const checkKeyPress = (e) =>{
    const { key, keyCode } = e;
    console.log(key, keyCode)
    if (keyCode === 13 ) {
      alert(input);
    }
  }

  useEffect(()=>{
    window.addEventListener("keydown", checkKeyPress)
    return ()=>{
      window.removeEventListener("keydown", checkKeyPress)
    }
  }, [])
  
  return (
    <div>
      <header className="App-header">
        <input value={input} onChange={handleInputChange} />
       <button onClick={handleShowAlert}>Show Alert</button>
      </header>
    </div>
  );
}

I made one change which can be seen in the code snippet below . I removed the [] from dependency list of useEffect() and it started working fine . But now the issue is it is adding and removing event listener each time I add something to input . This is not a good practice I guess if we are creating a big application .

import React, { useEffect, useRef, useState } from 'react';

export default function ShowAlertExample() {

  const [input, setInput ] = useState('1');
  const handleInputChange = (e) => {
    setInput(e.target.value);
  }

  const handleShowAlert = () => {
    alert(input);
  }

  const checkKeyPress = (e) =>{
    const { key, keyCode } = e;
    console.log(key, keyCode)
    if (keyCode === 13 ) {
      alert(input);
    }
  }

  useEffect(()=>{
    window.addEventListener("keydown", checkKeyPress)
    console.log("event listener added")
    return ()=>{
      console.log("event listener removed")
      window.removeEventListener("keydown", checkKeyPress)
    }
  })
  
  return (
    <div>
      <header className="App-header">
        <input value={input} onChange={handleInputChange} />
       <button onClick={handleShowAlert}>Show Alert</button>
      </header>
    </div>
  );
}

Is there anyway I can add event listener with the desired functionality without causing any performance issue . That is when I press ‘Enter’ key , the alert should display the correct input . I have referred to the below stackoverflow post and tried using useCallback() but it didn’t work out .

https://stackoverflow.com/questions/55565444/how-to-register-event-with-useeffect-hooks#:~:text=hooks%20to%20below-,useEffect(()%20%3D%3E%20%7B%20window.,the%20effect%20once%2C%20imitating%20componentDidMount%20.

30 thoughts on “React keypress event taking only initial state values and not updated values”

Leave a Comment