如何在 React 中通过用户的键盘输入来设置状态?
How to setState by user's keyboard input in React?
我目前正在写一个2048游戏,检测用户的键盘输入,然后改变相应方向的状态;但我没有改变状态。我以此为参考来捕获输入命令。
然后设置一个名为 keyValue 的字符串来存储键盘输入的字符串值并在我的 addEventListener 中更新 keyValue。但是我没能在我的 componentDidMount 中通过 keyValue 来设置状态。我的代码如下。我之前也尝试在我的 addEventListner 中设置 setState,但它也失败了。有人能帮忙吗?谢谢
constructor(props) {
super(props);
this.state = {
board: Array(4).fill().map(x => Array(4).fill(0)),
score: 0,
end: false,
emptySpace: true,
left: false,
right: false,
up: false,
down: false
};
}
componentDidMount() {
var cmdDown = false;
var keyValue = "";
document.body.addEventListener('keydown', function (event) {
var key = event.keyCode || event.charCode || 0;
if ([37, 38, 39, 40].indexOf(key) !== -1) {
cmdDown = true;
if ([37].indexOf(key) !== -1) {
keyValue = "ArrowLeft";
} else if ([38].indexOf(key) !== -1) {
keyValue = "ArrowUp";
} else if ([39].indexOf(key) !== -1) {
keyValue = "ArrowRight";
} else if ([40].indexOf(key) !== 1) {
keyValue = "ArrowDown"
}
}
console.log(keyValue);
console.log('CMD DOWN: ' + cmdDown.toString());
});
document.body.addEventListener('keyup', function (event) {
var key = event.keyCode || event.charCode || 0;
if ([37, 38, 39, 40].indexOf(key) !== -1) {
cmdDown = false;
}
console.log('CMD DOWN: ' + cmdDown.toString());
});
if (keyValue === "ArrowUp") {
this.setState({ up: true });
this.setState({ down: false });
this.setState({ left: false });
this.setState({ right: false });
} else if (keyValue === "ArrowDown") {
this.setState({ up: false });
this.setState({ down: true });
this.setState({ left: false });
this.setState({ right: false });
} else if (keyValue === "ArrowLeft") {
this.setState({ up: false });
this.setState({ down: false });
this.setState({ left: true });
this.setState({ right: false });
} else if (keyValue === "ArrowRight") {
this.setState({ up: false });
this.setState({ down: false });
this.setState({ left: false });
this.setState({ right: true });
console.log(this.state.right)
}
}
我写了一个函数来打印我的状态。但是在日志中它总是打印错误。为什么我的状态在渲染时没有得到更新?有什么同步相关的吗?
printDir = () => {
console.log("up: " + this.state.up.toString());
console.log("down: " + this.state.down.toString());
console.log("left: " + this.state.left.toString());
console.log("right: " + this.state.right.toString());
}
<button onClick = {this.printDir}>dir</button>
如果你想使用事件监听器,你必须使用 ref
属性来访问 DOM。例如 <div ref={this.divRef} ...
和 componentDidMount()
你可以写 this.divRef.current.addEventListener('keydown', ...)
我在您的代码段中发现了两个问题:
- 您用于检查箭头键的 if-else 条件不在侦听器设置范围内,不会被触发
- 您在这里使用 ES5 函数语法,
this
对象将引用您的函数作用域,而不是 class 作用域。您可能希望使用 ES6 箭头函数语法来避免 this
对象范围问题
我目前正在写一个2048游戏,检测用户的键盘输入,然后改变相应方向的状态;但我没有改变状态。我以此为参考来捕获输入命令。
constructor(props) {
super(props);
this.state = {
board: Array(4).fill().map(x => Array(4).fill(0)),
score: 0,
end: false,
emptySpace: true,
left: false,
right: false,
up: false,
down: false
};
}
componentDidMount() {
var cmdDown = false;
var keyValue = "";
document.body.addEventListener('keydown', function (event) {
var key = event.keyCode || event.charCode || 0;
if ([37, 38, 39, 40].indexOf(key) !== -1) {
cmdDown = true;
if ([37].indexOf(key) !== -1) {
keyValue = "ArrowLeft";
} else if ([38].indexOf(key) !== -1) {
keyValue = "ArrowUp";
} else if ([39].indexOf(key) !== -1) {
keyValue = "ArrowRight";
} else if ([40].indexOf(key) !== 1) {
keyValue = "ArrowDown"
}
}
console.log(keyValue);
console.log('CMD DOWN: ' + cmdDown.toString());
});
document.body.addEventListener('keyup', function (event) {
var key = event.keyCode || event.charCode || 0;
if ([37, 38, 39, 40].indexOf(key) !== -1) {
cmdDown = false;
}
console.log('CMD DOWN: ' + cmdDown.toString());
});
if (keyValue === "ArrowUp") {
this.setState({ up: true });
this.setState({ down: false });
this.setState({ left: false });
this.setState({ right: false });
} else if (keyValue === "ArrowDown") {
this.setState({ up: false });
this.setState({ down: true });
this.setState({ left: false });
this.setState({ right: false });
} else if (keyValue === "ArrowLeft") {
this.setState({ up: false });
this.setState({ down: false });
this.setState({ left: true });
this.setState({ right: false });
} else if (keyValue === "ArrowRight") {
this.setState({ up: false });
this.setState({ down: false });
this.setState({ left: false });
this.setState({ right: true });
console.log(this.state.right)
}
}
我写了一个函数来打印我的状态。但是在日志中它总是打印错误。为什么我的状态在渲染时没有得到更新?有什么同步相关的吗?
printDir = () => {
console.log("up: " + this.state.up.toString());
console.log("down: " + this.state.down.toString());
console.log("left: " + this.state.left.toString());
console.log("right: " + this.state.right.toString());
}
<button onClick = {this.printDir}>dir</button>
如果你想使用事件监听器,你必须使用 ref
属性来访问 DOM。例如 <div ref={this.divRef} ...
和 componentDidMount()
你可以写 this.divRef.current.addEventListener('keydown', ...)
我在您的代码段中发现了两个问题:
- 您用于检查箭头键的 if-else 条件不在侦听器设置范围内,不会被触发
- 您在这里使用 ES5 函数语法,
this
对象将引用您的函数作用域,而不是 class 作用域。您可能希望使用 ES6 箭头函数语法来避免this
对象范围问题