反应按键事件仅采用初始状态值而不是更新值

sat*_*yam 4 javascript dom-events reactjs use-effect use-state

我正在创建一个 React 应用程序,其中有一种称为输入的状态,它正在从用户那里获取输入。我希望当我按下回车键时,警报应该显示正在设置状态的输入。但是,单击enter按键时,仅显示输入状态中设置的默认值。

但是,当我单击按钮(我创建该按钮是为了在警报中显示输入)时,警报中显示的输入是正确的。

请参阅下面的代码片段以供参考:

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

我做了一项更改,可以在下面的代码片段中看到。我[]从依赖项列表中删除了useEffect()它,它开始正常工作,但现在的问题是,每次我向输入添加内容时,它都会添加和删除事件侦听器。我想如果我们要创建一个大型应用程序,这不是一个好的做法。

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

无论如何,我是否可以添加具有所需功能的事件侦听器,而不会导致任何性能问题。也就是说,当我按下Enter按键时,警报应该显示正确的输入。我参考了下面的 Stack Overflow 帖子并尝试使用,useCallback()但没有成功。

/sf/ask/3889581111/#:~:text=hooks%20to%20below-,useEffect(()%20%3D%3E%20 %7B%20window.,%20effect%20once%2C%20imitating%20componentDidMount%20。

Lak*_*kur 14

由于您始终需要 的最新状态值input,因此您必须添加checkKeyPress到 的useEffect依赖项列表中,并且checkKeyPress它本身应该包含input在包装器useCallbackdeps 列表中。

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

  useEffect(() => {
    window.addEventListener("keydown", checkKeyPress);
    return () => {
      window.removeEventListener("keydown", checkKeyPress);
    };
  }, [checkKeyPress]);
Run Code Online (Sandbox Code Playgroud)

在旧代码中,空数组意味着您要向首次渲染后可用的useEffect事件侦听器添加事件侦听器。checkKeyPress现在就checkKeyPress结束了 的默认值input

您需要确保每次input更新时,最新的checkKeyPress(关闭最新的input)被添加为事件处理程序,并删除旧的。