Reputation: 1377
I am working on a react web application that consists of several pages. I've set up a react router that switches between the pages.
Something like:
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'));
On the pages themselves, I make use of react-router
Redirect
function to navigate to and fro. Something like:
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()}
...
This all works. However, on the one page, I use some key bindings.
I've learnt that the best way to assign key bindings is to do it when the component is created, like <MyWebpage onKeyDown={handleKeyDown} />
, but because of legacy reasons, that not easy for me and currently I do the key-bindings with :
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));}
I find that handleKeyDown
is still being called, even after I've navigated to another page. I've checked: componentWillUnmount
is called and executed.
So I'd like to figure out why my removeEventListener
is not working and how to fix them.
Upvotes: 1
Views: 603
Reputation: 7428
You should remove the same listener which you add. So I suggest to create a final version bound to this
in constructor
and manipulate with it in lifecycle callbacks:
.....
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);
}
.....
Upvotes: 3
Reputation: 40481
You should bind the methods inside the constructor. AddEventListener and RemoveEventListener should recieve the same instances of a method in order to work , and I suspect that binding returns a new “binded” method , so they doesn’t match .
After binding the methods in the Ctor , just pass then to the event handling , they will already be binded
Upvotes: 2
Reputation: 8102
You have to pass the same function as the second parameter to the addEventListener/removeEventListener from global window variable: That same goes for addEventLsitener:
componentDidMount () {
window.addEventListener("keydown", this.handleKeyDown);
}
componentWillUnmount(){
window.removeEventListener("keydown", this.handleKeyDown);
window.removeEventListener("keyup", this.handleKeyUp);
}
Upvotes: 0