0

I was trying to find a related question SO, but I haven't been able to.

In a SPA, clicking the browser's back button won't take the user to the previous view of your app -- it'll take you to whichever previous website you've visited.

I've tried doing something like the below:

import React from 'react';
import { useDispatch } from 'react-redux';
import { useHistory } from 'react-router-dom';
import styled from 'styled-components';

const Part0 = ({ history }) => {
    React.useEffect(() => {
        return () => {
            if (history?.action === 'POP') {
                console.log('pop0');
                history.goBack();
            }
        };
    }, []);

    return <ComponentContainer>part0</ComponentContainer>;
};

const Part1 = ({ history }) => {
    React.useEffect(() => {
        return () => {
            if (history?.action === 'POP') {
                console.log('pop1');
                history.goBack();
            }
        };
    }, []);

    return <ComponentContainer>part1</ComponentContainer>;
};

export default function Component() {
    const [page, setPage] = React.useState(0);
    const history = useHistory();
    const dispatch = useDispatch()

    const handleBack = React.useCallback(() => {
        history.goBack();
    }, []);

    const handleForward = React.useCallback(() => {
        history.push('');
        setPage(page + 1);
    }, [page]);

    return (
        <Main>
            <ContentContainer>
                {page === 0 && <Part0 history={history} />}
                {page === 1 && <Part1 history={history} />}
                <ButtonContainer>
                    <Button onClick={handleBack}>back</Button>
                    <Button onClick={handleForward}>forward</Button>
                </ButtonContainer>
            </ContentContainer>
        </Main>
    );
}

const Main = styled.div`
    display: flex;
    align-items: center;
    justify-content: center;
`;

const ContentContainer = styled.div`
    height: 20vh;
`;

const ButtonContainer = styled.div`
    display: flex;
    justifyContent: space-between;
    alignItems: flex-end;
    height: 100%;
    width: 25vw;
`

const Button = styled.div`
    width: 8rem;
    cursor: pointer;
    height: 3rem;
    border: 1px solid gray;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 0.5rem;
    transition: 0.5s;

    &:hover {
        background-color: #f1f1f1;
    }
`;

const ComponentContainer = styled.div`
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
`;

The related part is the history.push(''); whenever the user decides to move forward and the history.goBack() for when the user decides to click the browser's back button.

This didn't work, unfortunately. Is it possible to be able to handle the user clicking the browser's back button in a SPA with React?

Mike K
  • 7,621
  • 14
  • 60
  • 120
  • Did you enclose your Routes inside BrowserRouter? From my understanding, BrowerRouter automatically handles the back and forward button based on route information present in history object. – Siddhant Varma Nov 10 '20 at 13:35
  • Yes, but in a SPA, there is not manipulation of the history object, it just dynamic content based on user interaction. – Mike K Nov 10 '20 at 13:52

1 Answers1

1

To answer your question, you can intercept the back button event like this:

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

componentWillUnmount() {
    super.componentWillUnmount();
    // Unbind listener
    this.backListener();
}

as was answered in here

Alex Boutin
  • 157
  • 1
  • 8