javascript - 无法读取未定义的“键”的属性,在 React 中处理事件
问题描述
我的目标是拥有一个运行 Javascript 的按钮,roshtimer()
并且还有可用于运行命令的热键。例如,我希望我的用户可以选择单击屏幕上的按钮或按键盘上的“r”。
我在这个问题上遇到了很多麻烦,因为我对 React 还比较陌生。
class Timer extends Component {
constructor(props) {
super(props);
this.state = {
time: 0,
roshDead: false,
roshDeathTime: 0,
aegisExpireTime: 0,
roshRespawnTime1: 0,
roshRespawnTime2: 0,
start: 0,
isOn: false,
};
this.startTimer = this.startTimer.bind(this);
this.stopTimer = this.stopTimer.bind(this);
this.resetTimer = this.resetTimer.bind(this);
this.roshTimer = this.roshTimer.bind(this);
this.roshButton = React.createRef();
this.handleRoshHotkey = this.handleRoshHotkey.bind(this);
}
componentDidMount() {
document.addEventListener("keydown", this.handleRoshHotkey);
}
componentWillUnmount() {
document.removeEventListener("keydown", this.handleRoshHotkey);
}
handleRoshClick() {
console.log("button was clicked!");
this.roshTimer();
}
handleRoshHotkey = (e) => {
if (e.key === "r" || e.keyCode === 13) {
console.log("hotkey was pressed!");
this.roshTimer();
}
};
startTimer() {
...
}
stopTimer() {
...
}
resetTimer() {
...
}
roshTimer() {
//compute rosh timers
let roshDeathTime = this.state.time;
let newAegisExpire = this.state.time + 300000; //5 mins = 300000 milliseconds
let newRespTime1 = this.state.time + 480000; // 8 mins = 480000 milliseconds
let newRespTime2 = this.state.time + 660000; // 11 mins = 660000 milliseconds
this.setState({
roshDeathTime: this.state.time,
aegisExpireTime: newAegisExpire,
roshRespawnTime1: newRespTime1,
roshRespawnTime2: newRespTime2,
roshDead: true,
});
//format rosh timers
...
//log to console for my own sanity
console.log(roshDeathTime, newAegisExpire, newRespTime1, newRespTime2);
//copy to user's clipboard
navigator.clipboard.writeText(
newAegisExpire + " " + newRespTime1 + " " + newRespTime2
);
}
render() {
let start =
this.state.time == 0 ? (
<button onClick={this.startTimer}>start</button>
) : null;
let stop = this.state.isOn ? (
<button onClick={this.stopTimer}>stop</button>
) : null;
let reset =
this.state.time != 0 && !this.state.isOn ? (
<button class="red" onClick={this.resetTimer}>
reset
</button>
) : null;
let resume =
this.state.time != 0 && !this.state.isOn ? (
<button class="green" onClick={this.startTimer}>
resume
</button>
) : null;
let rosh = this.state.isOn ? (
<div className={this.state.focused ? "focused" : ""}>
<button
onClick={() => this.handleRoshClick()}
autoFocus
ref={(c) => (this._input = c)}
>
{" "}
Rosh died!{" "}
</button>
</div>
) : null;
return (
<div>
<h3>
Timer: {prettyMilliseconds(this.state.time, { colonNotation: true })}
</h3>
{start}
{resume}
{stop}
{reset}
<div ref={this.roshButton} autofocus onKeyDown={() => this.handleRoshHotkey()} tabIndex={1}>
{rosh}
</div>
</div>
);
}
}
export default Timer;
目前,我可以运行我的应用程序并发送垃圾邮件“Rosh 死了!” 按钮并查看预期的输出。如果我点击网页上的任何地方,我就可以使用热键来获得预期的输出。但是,如果我在手动单击按钮之前使用热键,应用程序会崩溃,我会收到欢迎
TypeError: Cannot read property 'key' of undefined
进一步说明我的问题在这里:
handleRoshHotkey = (e) => {
if (e.key === "r" || e.keyCode === 13){ <-------------
console.log("hotkey was pressed!");
this.roshTimer();
}
};
这是一个示例控制台日志,直到它崩溃:
button was clicked!
1134 "5:01" "8:01" "11:01"
button was clicked!
1878 "5:01" "8:01" "11:01"
hotkey as pressed!
4318 "5:04" "8:04" "11:04"
hotkey was pressed!
5338 "5:05" "8:05" "11:05"
button was clicked!
8142 "5:08" "8:08" "11:08"
Uncaught TypeError: Cannot read property 'key' of undefined
.
. //(hundreds of lines of traceback follow)
.
hotkey was pressed!
11194 "5:11" "8:11" "11:11"
谢谢!
解决方案
两件事情:
主要问题是当你渲染时,你正在做
onKeyDown={() => this.handleRoshHotkey()}
...它
handleRoshHotkey
没有参数调用,这就是你得到错误的原因。由于您已bind
在构造函数中使用,请将其更改为:onKeyDown={this.handleRoshHotkey}
在 React 中使用处理程序就足够了,您也不想通过 使用它
addEventListener
,因此删除该代码(我猜您添加它是为了调试)。您可以完全删除componentDidMount
andcomponentWillUnmount
。
推荐阅读
- android - 如何在android中点击各种按钮的id并执行各种操作
- spring-boot - 执行 org.jetbrains.kotlin 时缺少必需的类
- swift - “字典使用两种存储方案:本机存储和可可存储”是什么意思?
- xml - XML 验证期间可能出现的命名空间问题
- python - pytorch 中的 CNN “预期 4 维输入用于 4 维权重 [32、1、5、5],但得到的 3 维输入大小为 [16、64、64]”
- angular - Angular 异步 Schematics 在迁移到 Angular 9 后停止工作:规则无法返回 Tree 或 Observable
不再 - expression - $ & || 的优先级是什么 在后缀表达式中
- polkadot-js - 是什么导致了这个无效的 JSON ABI 结构错误?
- linux - 从 udev 规则中调用变量
- regex - 在Textpad中如何仅替换部分字符串中的空格