【发布时间】:2021-11-10 03:18:03
【问题描述】:
我正在做一个需要封装用户输入的字母的项目
const { useState, useEffect } = React;
function App() {
const [usedLetter,setUsedLetter] = useState([])
useEffect(()=>{
window.addEventListener('keydown', handleKeydown);
return () => {
window.removeEventListener('keydown',handleKeydown);
}
},[])
function handleKeydown(event){
const letter = event.key;
setUsedLetter(usedLetter => [...usedLetter,letter])
console.log(usedLetter);
}
return (
<div className="App">
<p>Used letter : {usedLetter}</p>
</div>
);
}
ReactDOM.render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
这段代码产生了一个奇怪的行为。当我从反应开发者工具监控状态时,一切正常。结果在浏览器上显示正常。但是当涉及到控制台时,特别是console.log(usedLetter); 存储在usedLetter 中的值即使在我击中了多个字符之后也什么都不是。我曾尝试通过useEffect 访问usedLetter,它可以工作,但很不方便,因为我不得不中断流程并在事件侦听器回调之外访问它
谁能告诉我为什么会发生这种情况以及我如何才能在事件侦听器回调中获得真正的usedLetter(浏览器上的一个节目)?
谢谢一百万
【问题讨论】:
-
状态保证在整个渲染周期内保持稳定(除非发生突变),因此更新的状态值在下一个周期之前不可用(因此您的 console.log 反映了未更新的状态) .这回答了你的问题了吗? useState set method not reflecting change immediately
-
是的,我预计
console.log比usedLetter持有的实际值落后 1 步。但现实情况是,console引用的usedLetter一直没有任何内容。我认为这与您的链接建议的关闭更相关。 -
是的,我没有仔细阅读你的 sn-p。这绝对是由于仅在第一次安装时才添加侦听器而导致的关闭问题。 (处理程序是在每次渲染时声明的,所以不会遇到这个问题,但是监听器已经在它上面形成了一个闭包,就像在第一次安装时声明的那样)。最干净的解决方案就是将
usedLetter添加到useEffect 的依赖数组中。useEffect(() => {...}, [usedLetter]); -
Tks 老兄,它就像我预期的那样工作 :)
标签: javascript reactjs