React Router v4 - How to detect back button navigation vs url refresh?

4.4k views Asked by At

I have a url at /page (PAGE A) where I want to detect if the page was navigated to with history back from (PAGE B) or if the user was on (PAGE A) and manually refreshed the page from the URL bar refresh button (without using history back).

I looked into all the history, location, props by react router but didn't find a way to differentiate how the user navigated to the page.

In both scenarios, the history.action == 'POP' is the history action. Ideally it would be 'POP' when using the back button in the app to go back from page b to page a, and when on page a, when refreshing the page, it would be something other than 'POP' like 'REFRESH' for example.

How can we differentiate between both of them to run different logic in our app, since both trigger 'POP'?

2

There are 2 answers

1
AudioBubble On

I think this will at least point your in the right direction. Navigate to yourwebsite.com.

let current_page = history.state.key

if(history.action == 'POP') {
  if(history.state.key == current_page) {
    return 'page was refreshed'
  }
  return 'back button was pressed'
}
4
Nosvan On

Instead of comparing the history key, you can compare the pathname, for example, if you are in the page "/page1/page2" and hit refresh, the new location is the same. But if you hit the back action, the new location will be "/page1/".

This solution also uses a listener to listen to any action coming from history.

  componentDidMount() {
    const unlisten = history.listen((location, action) => {
        if (action == 'POP') {
          \\ thisLocation is the current location of your page
          if (location.pathname != '/thisLocation/') {
            alert('Back Pressed: ' + String(location.pathname));
          } else {
            alert('Refreshed: ' + String(location.pathname));
          }
        }
    });
    this.setState({ ...this.state, unlisten: unlisten });
  }

  componentWillUnmount() {
    this.state.unlisten();
  }

You can see more details in the link provided by Rei Dien as a comment of your question: https://www.npmjs.com/package/history

[EDIT]

Another way to do this is using https://www.npmjs.com/package/react-router-last-location and doing this:

import { useLastLocation } from 'react-router-last-location';

  componentDidMount() {
    const unlisten = history.listen((location, action) => {
          const lastLocation = useLastLocation();
          if (location.pathname == lastLocation.pathname) {
            alert('Back Pressed: ' + String(location.pathname));
          }
        }
    });
    this.setState({ ...this.state, unlisten: unlisten });
  }

  componentWillUnmount() {
    this.state.unlisten();
  }

The downside is that there is no difference between activating the back action or clicking in a link that goes to the page that you was before, both would be detected as pressing back. If you don't want a new dependency, you can do it manually as stated in https://github.com/ReactTraining/react-router/issues/1066#issuecomment-412907443 creating a middleware.