React—Change a components state on window.history.popstate

Mirror318 picture Mirror318 · Nov 16, 2017 · Viewed 7.6k times · Source

I have a React component that pushes song IDs to the url when the state changes. My problem is that when a user clicks 'back' on their browser, I need to change the state of my SongApp component. How do I do this?

class SongApp extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      song: props.songId
    }

    this.setSong = this.setSong.bind(this);
  }

  setSong(e) {
    var songId = e.target.id;
    this.setState({song: songId})
    window.history.pushState({song: songId}, '', '?s='+songId)
  }

  render() {
    var id = this.state.song;

    var content = id ? <SongDisplay lyrics={ this.props.songData[id].lyrics } /> : <SongIndex songData={this.props.songData} setSong={this.setSong}/>
    return(
      <div className="song-app">
        {content}
      </div>
    )
  }
}

window.addEventListener('popstate', function(event) {
  console.log('popstate fired!');
  debugger;
  if(event.state.song) {
    // change SongApp state
  }
});

Answer

Mirror318 picture Mirror318 · Nov 17, 2017

I found out you can attach the component's method to a listener:

  componentDidMount() {
    window.addEventListener("popstate", this.setSongFromHistory);
  }

  setSongFromHistory(e) {
    if(e.state.song){
      e.preventDefault(); // stop request to server for new html
      e.stopPropagation();
      this.setState({song: e.state.song});
      $('html,body').scrollTop(0);
    }
  }