使用箭头函数表示法时“按键”事件被调用两次
'Keypress" event called twice when using arrow function notation
我希望每次按下该键时都会记录一次按下的每个键,但是每次按下时每个键都会记录两次。但是,仅当对传递给事件侦听器的函数使用箭头表示法时。
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>
)
}
}
令人困惑的是,此代码在 jsfiddle 上按预期工作:
https://jsfiddle.net/wgqs75pr/4/
但是,它在全新的 create-react-app 上无法按预期工作。
为什么每次 KeyPress 都会调用两次 this.KeyPress?
对我来说,仍然使用 class 组件没有意义,它们不适合更大的组件。
如果是因为您遵循了具有 stateless 和 state 组件的旧指南,则在 React hooks 发布时此模式已被弃用宣布。我建议您研究一下钩子如何解决像这样的许多烦人的错误。
无论如何,我建议你把它放在生命周期方法中。你可以在这里阅读更多关于它们的信息:
https://reactjs.org/docs/react-component.html#render
请检查代码,我还在组件卸载时添加了 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"))
每个键是键被记录两次的原因是因为 keypress
有两个事件处理程序。这很可能是因为 React 在 strict mode 中是 运行,所以构造函数被调用了两次。这也是代码在 jsfiddle 上运行良好的原因,因为在生产模式下禁用了严格模式。
要解决此问题,请在 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>
)
}
}
删除 componentWillUnmount
中的事件侦听器可能也很有用,否则您可能会遇到意外行为。
我希望每次按下该键时都会记录一次按下的每个键,但是每次按下时每个键都会记录两次。但是,仅当对传递给事件侦听器的函数使用箭头表示法时。
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>
)
}
}
令人困惑的是,此代码在 jsfiddle 上按预期工作: https://jsfiddle.net/wgqs75pr/4/ 但是,它在全新的 create-react-app 上无法按预期工作。
为什么每次 KeyPress 都会调用两次 this.KeyPress?
对我来说,仍然使用 class 组件没有意义,它们不适合更大的组件。
如果是因为您遵循了具有 stateless 和 state 组件的旧指南,则在 React hooks 发布时此模式已被弃用宣布。我建议您研究一下钩子如何解决像这样的许多烦人的错误。
无论如何,我建议你把它放在生命周期方法中。你可以在这里阅读更多关于它们的信息: https://reactjs.org/docs/react-component.html#render
请检查代码,我还在组件卸载时添加了 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"))
每个键是键被记录两次的原因是因为 keypress
有两个事件处理程序。这很可能是因为 React 在 strict mode 中是 运行,所以构造函数被调用了两次。这也是代码在 jsfiddle 上运行良好的原因,因为在生产模式下禁用了严格模式。
要解决此问题,请在 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>
)
}
}
删除 componentWillUnmount
中的事件侦听器可能也很有用,否则您可能会遇到意外行为。