How can I log the react history stack?

Viewed 3356

As far as I know, react props keep an history of all the links that you have been visiting each time that you either update a page, or navigate to a new one. This history can be navigated using props.history.go(-number)

For example if I navigate to

/home --> /home/startup --> /error

My history will be saved somewhere as ["/home", "/home/startup", "/error"]

And i trigger

history.go(-2) , I will be pushed to /home and the history stack will be reseted up to that point.

I'm asking this because I'm forced to keep a custom object tracking all the user navigation, to be able to use back buttons in the site that redirect the user to specific checkpoints.

For example:

const pushBack = () => {

    let historyArr: Array<string> = getNavigationHistoryArr();
    historyArr.reverse();

    //check the amount of spots between our tracked history last element and the checkpoints
    let spotsToRedirect: number = 0;
    for (let i in historyArr) {
      if (redirectCheckpoints.includes(historyArr[i])) {
        break;
      }
      spotsToRedirect--;
    }

    console.log("sportsToRedirect: "+spotsToRedirect)
    //whenever you have a long navigation stack
    if (spotsToRedirect < 0 && spotsToRedirect * -1 != historyArr.length) {
      removeSessionStorageEl(spotsToRedirect * -1)
      history.go(spotsToRedirect);
    }
    else {
      removeSessionStorageEl(historyArr.length)
      if(process.env.REACT_APP_TYPO3_URL){
        window.location.assign(process.env.REACT_APP_TYPO3_URL);
      }else{
        history.push("/")
      }
    }
  }

redirectCHeckpoints is:

export const redirectCheckpoints : Array<string> = [
    /home 
]

Point this code for example most of the times should work fine.

If I go to /home --> /error --> /error ---> /error ---> /error (cause I'm reloading the error page). The above code would yield a history.go(-4). Which would mean a redirect to /home deleting the rest of the history. But for some reason it fails randomly, specifically if I force weird behaviors like reloading the error page all the time.

I keep track of the history by using this didUpdate and didMount in my app.tsx file

    componentDidUpdate(prevProps) {
        
        if (this.props.location.pathname !== prevProps.location.pathname) {
          console.log("--didupdate1--")
          console.log("this.props.location.key: ",this.props.location.key)
        console.log("this.props.location.pathname: ",this.props.location.pathname)
          this.setDataLayer()
        }
    
        if (this.props.location.key !== prevProps.location.key || this.props.location.pathname !== prevProps.location.pathname) {
          trackNavHistory(this.props.location.pathname);
        }
      }

componentDidMount() {
   
    trackNavHistory(this.props.location.pathname);

  }

So... is there a way to read the history stack in real time and log its data? Maybe it will help me debug the error.

1 Answers

React by itself has no routing, so I will assume React Router here.

And the answer is: no, you don't have any access to the history stack.

It works this way because that is how the History API works.

Why? Because when access the history prop, by default, you are using window.history underneath. The History API does not allow inspecting paths because it would be a privacy flaw, since the history state is about the whole browser history in a tab, not just your domain.

You can try using Router (instead of BrowserRouter I guess you are using) which receives a history prop, where you can implement your own history abstraction:

import React from "react";
import ReactDOM from "react-dom";
import { Router } from "react-router";

const customHistory = {
  push(...) {
    ...
  }
}

ReactDOM.render(
  <Router history={customHistory}>
    <App />
  </Router>,
  node
);

Another option is listening to history changes:

const unlisten = history.listen(({ location, action }) => {
  console.log(action, location.pathname, location.state);
});

history in the snippet above is the history object passed to the Router component. It may be accessed before being passed to the component, through this.props.history or through the useHistory hook.

I don't think any of those implementations solve your issue anyway because they are only able to listen to navigation changes after scripts are loaded, so it will not catch paths added to history when the page is reloaded.

Related