Javascript ';按键;使用箭头函数表示法时调用两次事件
我希望每按一次键都会记录一次,但是每按一次键都会记录两次。但是,仅当对传递给事件侦听器的函数使用箭头符号时Javascript ';按键;使用箭头函数表示法时调用两次事件,javascript,reactjs,create-react-app,Javascript,Reactjs,Create React App,我希望每按一次键都会记录一次,但是每按一次键都会记录两次。但是,仅当对传递给事件侦听器的函数使用箭头符号时 class Test extends React.Component { constructor(props) { super(props) window.addEventListener('keypress', (e) => this.KeyPress(e)) //works fine with this.KeyPress } KeyPress(e
class Test extends React.Component {
constructor(props) {
super(props)
window.addEventListener('keypress', (e) => this.KeyPress(e)) //works fine with this.KeyPress
}
KeyPress(e){
console.log(e.key)
}
render() {
return (
<div>
<h1>hi there</h1>
</div>
)
}
}
类测试扩展了React.Component{
建造师(道具){
超级(道具)
window.addEventListener('keypress',(e)=>this.keypress(e))//可以与this.keypress配合使用
}
按键(e){
console.log(e.key)
}
render(){
返回(
你好
)
}
}
令人困惑的是,这段代码在JSFIDLE上的效果与预期的一样:
但是,在一个全新的create-react应用程序上,它并没有像预期的那样工作
为什么每次按键都会调用this.KeyPress两次?对我来说,仍然使用类组件是没有意义的,它们不适合较大的组件 如果是因为您遵循了使用无状态和状态组件的旧指导,那么在宣布React钩子时,此模式已被弃用。我建议你研究一下钩子是如何解决很多这样令人讨厌的bug的 无论如何,我建议你把它放在生命周期方法中。您可以在此处阅读更多关于它们的信息: 请查看代码,我还在组件卸载时添加了removeEventListener
class Test extends React.Component {
constructor(props) {
super(props)
}
componentDidMount() {
window.addEventListener('keypress', (e) => this.KeyPress(e))
}
componentWillUnmount() {
window.removeEventListener('keypress', (e) => this.KeyPress(e))
}
KeyPress(e){
console.log(e.key)
}
render() {
return (
<div>
<h1>hi there</h1>
</div>
)
}
}
ReactDOM.render(<Test />, document.querySelector("#app"))
ReactDOM.render(<Test />, document.querySelector("#app"))
类测试扩展了React.Component{
建造师(道具){
超级(道具)
}
componentDidMount(){
window.addEventListener('keypress',(e)=>this.keypress(e))
}
组件将卸载(){
window.removeEventListener('keypress',(e)=>this.keypress(e))
}
按键(e){
console.log(e.key)
}
render(){
返回(
你好
)
}
}
ReactDOM.render(,document.querySelector(“#app”))
ReactDOM.render(,document.querySelector(“#app”))
每个按键记录两次的原因是,keypress
有两个事件处理程序。这很可能是因为react正在运行,因此构造函数被调用了两次。这也是代码在JSFIDLE上运行良好的原因,因为在生产模式中禁用了严格模式
要解决此问题,请在componentDidMount
生命周期函数中附加事件处理程序:
class Test extends React.Component {
constructor(props) {
super(props)
}
KeyPress(e){
console.log(e.key)
}
componentDidMount() {
window.addEventListener('keypress', (e) => this.keyPress(e))
}
render() {
return (
<div>
<h1>hi there</h1>
</div>
)
}
}
类测试扩展了React.Component{
建造师(道具){
超级(道具)
}
按键(e){
console.log(e.key)
}
componentDidMount(){
window.addEventListener('keypress',(e)=>this.keypress(e))
}
render(){
返回(
你好
)
}
}
删除
componentWillUnmount
中的事件侦听器也可能很有用,否则您可能会出现意外行为。您选择使用类组件而不是挂钩有什么原因吗?@ChristianMoen这是从更适合作为类组件的更大类中提取出来的。这并不能真正解决问题问题是,我知道更改为非箭头函数可以修复错误,但我想使用箭头符号来绕过this
的绑定。因此,我想知道为什么箭头符号版本与非箭头函数版本的工作原理不同。我更新了代码,在按键函数调用中使用箭头函数。不过,你可以通过使用功能组件跳过所有这些麻烦。我可能会根据你给出的所有理由现在重构成一个功能组件,但我是在理解之后,而不是解决方法。只是提醒一下,您在此处调用的removeEventListener
函数引用与挂载时添加的函数引用不同。您会使用window.addEventListener('keypress',this.keypress.bind(this))吗
?@samthecodingman可能是这样,但我刚刚完成了react教程,他们使用箭头符号来绕过这个
的绑定。