Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/474.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ';按键;使用箭头函数表示法时调用两次事件_Javascript_Reactjs_Create React App - Fatal编程技术网

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教程,他们使用箭头符号来绕过
这个
的绑定。