[英]State inside useEffect changing with delay
I'm trying to manipulate the DOM based on what's being typed ( text
) in an input in a React component:我正在尝试根据在 React 组件的输入中输入的内容( text
)来操作 DOM:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function App() {
const [text, setText] = useState("Initial value");
function handleChange(event) {
setText(event.target.value);
}
useEffect(() => {
function handleKeypress(event) {
console.log("text", text);
// do something with the DOM with text
}
document.addEventListener("keydown", handleKeypress);
return () => {
document.removeEventListener("keydown", handleKeypress);
};
}, [text]);
return (
<div id="keys">
<input type="text" onChange={handleChange} value={text} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
It works, but something strange happens.它有效,但发生了一些奇怪的事情。 text
won't change unless keydown
is triggered a second time.除非第二次触发keydown
,否则text
不会改变。
For example, if you press a
, console.log("text", text)
will log Initial value
.例如,如果您按下a
, console.log("text", text)
将记录Initial value
。 It won't log a
.它不会记录a
. I think there's some kind of delay.我认为有某种延迟。
Why is this?为什么是这样? And how to change the code so that console.log("text", text)
logs the key that's being pressed?以及如何更改代码以便console.log("text", text)
记录正在按下的键?
Live code: https://codesandbox.io/s/react-hooks-useeffect-forked-sfujxi?file=/src/index.js实时代码: https ://codesandbox.io/s/react-hooks-useeffect-forked-sfujxi?file=/src/index.js
Note: The reason I'm using the event listener is that I want the code to also run when, for example, I press Ctrl + Key
(in that situation text
doesn't change).注意:我使用事件监听器的原因是我希望代码也能在我按下Ctrl + Key
时运行(在这种情况下text
不会改变)。
It seems that this is because the text
state is updated in the next render of the component, but the event block is still using the old value before the update.看起来这是因为在组件的下一次渲染中更新了text
状态,但是事件块仍在使用更新前的旧值。
Try not to use a event listener but let useEffect
capture the change of the text
state and it should log the correct input (when text
changes):尽量不要使用事件侦听器,但让useEffect
捕获text
状态的更改,它应该记录正确的输入(当text
更改时):
useEffect(() => {
console.log("text", text);
}, [text]);
Alternatively if the goal is to log the key pressed, perhaps consider to just capture it with event
since the event
will have the value of the pressed key.或者,如果目标是记录按下的键,也许考虑只用event
捕获它,因为event
将具有按下的键的值。
There is no need to read from text
state for this approach, instead perhaps consider to set the captured value as a state for display in some other components.这种方法不需要从text
状态中读取,而是可以考虑将捕获的值设置为在其他一些组件中显示的状态。
useEffect(() => {
function handleKeypress(event) {
console.log(event.keyCode);
}
document.addEventListener("keydown", handleKeypress);
return () => {
document.removeEventListener("keydown", handleKeypress);
};
}, []);
Considering the Note that you have provided in your question If you want the handleKeypress
function to run when the user presses a key combination, such as Ctrl + Key
, you can use the event.ctrlKey
property to check if the Ctrl key is being pressed.考虑到您在问题中提供的注释如果您希望handleKeypress
函数在用户按下组合键(例如Ctrl + Key
)时运行,您可以使用event.ctrlKey
属性检查是否按下了 Ctrl 键。
function handleKeypress(event) {
if (event.ctrlKey) {
console.log("Ctrl + Key was pressed");
}
}
If you want to check for specific key combinations for example, to check for Ctrl + S
you can do that using event.key property
.例如,如果您想检查特定的组合键,要检查Ctrl + S
,您可以使用event.key property
来做到这一点。
function handleKeypress(event) {
if (event.ctrlKey && event.key === "s") {
console.log("Ctrl + S was pressed");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.