Search code examples
javascriptreactjsrouterbrowser-history

React Router make back prevent forward


Requirement: When clicking on a button that pushes a #info route to show a full screen overlay component, closing the modal or pressing back should dismiss the overlay rather than go to the previous page.

e.g. on page 1, go to page 2. On page 2, press button to show overlay. Press back or closing overlay should dismiss overlay and remain on page 2.

The problem: When going back to page 2 I still have forward history to go to the overlay route.

I've searched for ways and couldn't find a solution to delete forward history.

My code is as such: If overlay is shown:

this.props.router.push(this.props.router.getCurrentLocation().pathname + '#info')

Then I have a code to goBack when overylay is closed or when pressing back button:

onBackButtonEvent () {
  if (this.props.renderOverlay) {
    this.setState({
      overlayRoutePushed: false
    })
    this.props.closeOverlay()
  }
}

closeOverylayAndBack () {
  this.setState({
    overlayRoutePushed: false
  })
  this.props.closeOverlay()
  this.props.router.goBack()
}

componentDidMount () {
  window.onpopstate = this.onBackButtonEvent
}

In order to detect back button with window.onpopstate I have to push a route. I tried to replaceRoute with #info when overlay shown and just close overlay when pressing back but I can't prevent default of route.goBack().

Any ideas?


Solution

  • I wasn't able to find a way to prevent forward or remove forward history so my final resort was to remove using hash and just show the overlay when i hit forward and hide when I hit back:

    this.props.router.push({
        pathname: this.props.router.getCurrentLocation().pathname,
        state: {overlay: true}
     })
    

    This is to remove the #, and if I don't change state push will actually be using replace() which won't let me handle onPopState.

    Then I check to see if state is changed when I pop back and forth:

    componentWillReceiveProps (nextProps) {
        if (nextProps.router.location.state) {
             if (nextProps.router.location.state.overlay) {
                 this.showOverylay()
             }
         }
     }