我正在构建一个简单的俄罗斯方块应用程序,在其中我有可以点击的按钮的gameoby。
目前它是一个react应用程序,我处理点击的方式定义如下:
const [keyPressed, setKeyPressed] = useState([])
const onKeydown = (e) => {
const currentKey = e.key.toLowerCase()
const localKeyPressed = [...keyPressed]
localKeyPressed.push(currentKey)
setKeyPressed(localKeyPressed)
}
const onKeyUp = (e) => {
const currentKey = e.key.toLowerCase()
const localKeyPressed = keyPressed
localKeyPressed.pop(currentKey)
setKeyPressed(localKeyPressed)
}
useEffect(() => {
document.addEventListener('keydown', onKeydown)
document.addEventListener('keyup', onKeyUp)
return () => {
document.removeEventListener('keydown', onKeydown)
document.removeEventListener('keyup', onKeyUp)
}
}, [])
我想要一个数组,当我连续按两个键(例如:'A','B')时,我得到的是A,B,目前不是这样的,我只是得到了A,我不知道确切的原因。
关于这个话题有什么帮助吗?
非常感谢!
发布于 2021-03-25 04:28:04
事件处理函数依赖于当前状态keyPressed
。当您将它们附加到useEffect
中的事件时,这些函数将指向原始的keyPressed
状态,这是一个空数组。每当更新状态时,都会将当前值添加到空数组中,并将其设置为新状态。
useEffect
依赖项数组为空,因此在卸载组件之前不会再次调用它。一种解决方案是将函数添加到依赖关系数组,以便在每次呈现时添加和删除事件处理程序。另一种选择是避免依赖项的需要。当新状态依赖于前一个状态时,请使用useState
的functional updates形式,以避免将前一个状态用作依赖项。
此外,不要在onKeyUp
中改变状态,因为const localKeyPressed = keyPressed
不会克隆原始状态,所以使用数组扩展来完成此操作。
const { useState, useEffect } = React
const Demo = () => {
const [keyPressed, setKeyPressed] = useState([])
useEffect(() => {
const onKeydown = e => {
setKeyPressed(oldState => [
...oldState,
e.key.toLowerCase()
])
}
const onKeyUp = e => {
setKeyPressed(oldState => {
const newState = [...oldState]
newState.pop()
return newState
})
}
document.addEventListener('keydown', onKeydown)
document.addEventListener('keyup', onKeyUp)
return () => {
document.removeEventListener('keydown', onKeydown)
document.removeEventListener('keyup', onKeyUp)
}
}, [])
return (
<div>
{
JSON.stringify(keyPressed)
}
</div>
)
}
ReactDOM.render(
<Demo />,
root
)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
https://stackoverflow.com/questions/66786184
复制相似问题