Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intercept/handle browser's back button in React-router?

I'm using Material-ui's Tabs, which are controlled and I'm using them for (React-router) Links like this:

    <Tab value={0} label="dashboard" containerElement={<Link to="/dashboard/home"/>}/>
    <Tab value={1} label="users" containerElement={<Link to="/dashboard/users"/>} />
  <Tab value={2} label="data" containerElement={<Link to="/dashboard/data"/>} />

If I'm currenlty visting dashboard/data and I click browser's back button I go (for example) to dashboard/users but the highlighted Tab still stays on dashboard/data (value=2)

I can change by setting state, but I don't know how to handle the event when the browser's back button is pressed?

I've found this:

window.onpopstate = this.onBackButtonEvent;

but this is called each time state is changed (not only on back button event)

like image 637
high incompetance Avatar asked Sep 06 '16 06:09

high incompetance


People also ask

How do you handle back button of browser in react?

It depends on the type of Router you use in React. If you use BrowserRouter from react-router (not available in react-router v4 though), as mentioned above, you can use the action 'POP' to intercept the browser back button.

How do you know if browser Back button is clicked react?

If it's 'POP' , then the back button is pressed. With a function component, we can listen to the history object for changes. history has the action property which returns the action that's being done. If it's 'POP' , then we know that the user pressed the back button.


4 Answers

This is a bit old question and you've probably already got your answer, but for people like me who needed this, I'm leaving this answer.

Using react-router made the job simple as such:

import { browserHistory } from 'react-router';

componentDidMount() {
    super.componentDidMount();

    this.onScrollNearBottom(this.scrollToLoad);

    this.backListener = browserHistory.listen(location => {
      if (location.action === "POP") {
        // Do your stuff
      }
    });
  }

componentWillUnmount() {
    super.componentWillUnmount();
    // Unbind listener
    this.backListener();
}
like image 85
Jay Shin Avatar answered Oct 23 '22 01:10

Jay Shin


Using hooks you can detect the back and forward buttons

import { useHistory } from 'react-router-dom'


const [ locationKeys, setLocationKeys ] = useState([])
const history = useHistory()

useEffect(() => {
  return history.listen(location => {
    if (history.action === 'PUSH') {
      setLocationKeys([ location.key ])
    }

    if (history.action === 'POP') {
      if (locationKeys[1] === location.key) {
        setLocationKeys(([ _, ...keys ]) => keys)

        // Handle forward event

      } else {
        setLocationKeys((keys) => [ location.key, ...keys ])

        // Handle back event

      }
    }
  })
}, [ locationKeys, ])
like image 33
Nicolas Keller Avatar answered Oct 23 '22 03:10

Nicolas Keller


here is how I ended up doing it:

componentDidMount() {
    this._isMounted = true;
    window.onpopstate = ()=> {
      if(this._isMounted) {
        const { hash } = location;
        if(hash.indexOf('home')>-1 && this.state.value!==0)
          this.setState({value: 0})
        if(hash.indexOf('users')>-1 && this.state.value!==1)
          this.setState({value: 1})
        if(hash.indexOf('data')>-1 && this.state.value!==2)
          this.setState({value: 2})
      }
    }
  }

thanks everybody for helping lol

like image 22
high incompetance Avatar answered Oct 23 '22 03:10

high incompetance


Hooks sample

const {history} = useRouter();
  useEffect(() => {
    return () => {
      // && history.location.pathname === "any specific path")
      if (history.action === "POP") {
        history.replace(history.location.pathname, /* the new state */);
      }
    };
  }, [history])

I don't use history.listen because it doesn't affect the state

const disposeListener = history.listen(navData => {
        if (navData.pathname === "/props") {
            navData.state = /* the new state */;
        }
    });
like image 22
Bnaya Avatar answered Oct 23 '22 01:10

Bnaya