Source:  Twitter logo

There seems to be no API way to detect if you can go back from the current page in an app. One can check the history length, but that includes the forward and backward stack.

I want to display the back button only when the user actually can go back.

You can do it by checking history.action if its value is POP, then there is no route to go back. That's the only way I found.

<Button
  onClick={() => {
    if (history.action !== 'POP') history.goBack();
  }}
  disabled={history.action === 'POP'}
/>
12 users liked answer #0dislike answer #012
Haseeb Anwar profile pic
Haseeb Anwar

You can check loction.key if you have a location key that means you routed in-app. But if you don't that means you come from outside of the app or you just open the app in a new tab etc.

import { useHistory, useLocation } from "react-router-dom";
const HISTORY = useHistory();
const LOCATION = useLocation();

<Button
  onClick={() => {
    if (LOCATION.key) {
      HISTORY.goBack();
    }
  }}
  disabled={!LOCATION.key}
/>;
11 users liked answer #1dislike answer #111
Tugay Yaldız profile pic
Tugay Yaldız

I think I found a workaround

There is onpopstate event:

Calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event is only triggered by performing a browser action, such as clicking on the back button (or calling history.back() in JavaScript), when navigating between two history entries for the same document.

And I checked it: react router saves at state a key property: On history walking it may contains a data like: event.state: {key: "jr2go2", state: undefined}

And when we go back to last page on wich we entered the site or app, this state property will be null: event.state: null ,

So we can handle it with redux + rxjs (for example) like this:

// epic
export const handleHistoryWalkEpic = () =>
  fromEvent<PopStateEvent>(window, 'popstate')
  .pipe(
    map(event => setCanGoBack(!!event.state)),
  )

// reducer
case NavigationBarActionsTypes.SET_CAN_GO_BACK:
  return {
    ...state,
    canGoBack: action.payload.canGoBack,
  }

And you should set canGoBack to true on any push history action, it's possible with your any router handler component:

componentWillUpdate(nextProps: any) {
    let { location } = this.props;

    if (nextProps.history.action === 'PUSH') {
      this.props.setCanGoBack()
    }
}
3 users liked answer #2dislike answer #23
Mikhail Shemenyov profile pic
Mikhail Shemenyov

You can do it by checking if location.history is > 2.

Example to show or not the back button in your app:

onBack={ history.length > 2 ? () => { history.goBack() } : null }
-2 users liked answer #3dislike answer #3-2
diogopalhais profile pic
diogopalhais

it gives 'POP' and 'PUSH' value using this.props.location.action

-4 users liked answer #4dislike answer #4-4
Mohit Verma profile pic
Mohit Verma

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).