反应js eventListener未按预期移除

时间:2018-08-29 08:48:46

标签: javascript reactjs event-handling react-router addeventlistener

我正在研究一个由几个页面组成的React Web应用程序。 我已经设置了一个在页面之间切换的反应路由器。

类似的东西:

render((
    <Provider store={store}>
        <BrowserRouter>
            <Switch>
                <Route exact path='/' component={RedirectPage} />
                <Route exact path='/sign-in' render={() => <PlayerSelect />}/>
                <Route exact path='/most-recent-scenario' render={() => <ScenarioInterface />} />
                <Route exact path='/home' render={() => <Home />} />
                <Route exact path='/scenario/:id' render={props => <Index {...props} /> } />
                <Route exact path='/user-select' render={() => <UserSelect />}/>
            </Switch>
        </BrowserRouter>
    </Provider>
), document.getElementById('root'));

在页面本身上,我使用react-router Redirect函数来回浏览。像这样:

import { Redirect} from 'react-router-dom'

class Index extends React.Component {
  state = {
    ...
    redirect: false,
    redirect_to: ""
  }

  setRedirect = (page) => {
      this.setState({
      redirect: true,
      redirect_to: page})
  }

  renderRedirect = () => {
  if (this.state.redirect) {
      return <Redirect to={this.state.redirect_to} /> }
  }

  render(){
    return (
        <div className={classes.root}>
          {this.renderRedirect()}
          ...

一切正常。但是,在一页上,我使用了一些键绑定。

我了解到,分配键绑定的最佳方法是在创建组件时进行操作,例如<MyWebpage onKeyDown={handleKeyDown} />,但是由于遗留原因,这对我来说并不容易,目前我做键-绑定:

  componentDidMount(){
    document.addEventListener("keydown", this.handleKeyDown.bind(this));
    document.addEventListener("keyup", this.handleKeyUp.bind(this));}

  componentWillUnmount(){
    document.removeEventListener("keydown", this.handleKeyDown.bind(this));
    document.removeEventListener("keyup", this.handleKeyUp.bind(this));}

我发现handleKeyDown仍在被调用,即使我导航到另一个页面也是如此。我检查了:componentWillUnmount被调用并执行。

所以我想弄清楚为什么我的removeEventListener无法正常工作以及如何解决它们。

3 个答案:

答案 0 :(得分:2)

您应该将方法绑定到构造函数中。为了正常工作,AddEventListener和RemoveEventListener应该接收方法的相同实例,并且我怀疑绑定会返回新的“ binded”方法,因此它们不匹配。

在将方法绑定到Ctor中之后,只需将其传递给事件处理,它们将已经被绑定

答案 1 :(得分:2)

您应该删除添加的同一侦听器。因此,我建议在this中创建绑定到constructor的最终版本,并在生命周期回调中对其进行操作:

  .....

  constructor(props) {
    super(props);

    this.handleKeyDown = this.handleKeyDown.bind(this);
    this.handleKeyUp = this.handleKeyUp.bind(this);
  }

  componentDidMount() {
    document.addEventListener("keydown", this.handleKeyDown);
    document.addEventListener("keyup", this.handleKeyUp);
  }

  componentWillUnmount() {
    document.removeEventListener("keydown", this.handleKeyDown);
    document.removeEventListener("keyup", this.handleKeyUp);
  }

  .....

答案 2 :(得分:0)

您必须从全局 window 变量中将与第二个参数相同的函数传递给addEventListener / removeEventListener: addEventLsitener也是如此:

componentDidMount () {
  window.addEventListener("keydown", this.handleKeyDown);
}


componentWillUnmount(){
     window.removeEventListener("keydown", this.handleKeyDown);
     window.removeEventListener("keyup", this.handleKeyUp);
    }