noblerare
noblerare

Reputation: 11853

React - Keeping user on same page - prevent page refresh

I have a React/Redux application that takes the user through some basic setup steps and the last page is a page where live data is captured and recorded. I don't want the user to be able to Ctrl+R, F5 or Ctrl+F5 and refresh the page. Instead, the only way I want them to leave the page is to click a "Stop recording" button.

Currently, the application is built using a single HomeScreenComponent and I swap out the components of the page depending on the mode that the application is in. So for example, if it's in setup mode, it'll show Component A and if it's in record mode, it'll show Component B.

As it stands right now, if a user is in record mode, they are able to do Ctrl+R and refresh the page, taking you back to setup mode.

How do I prevent the user from refreshing the page and leaving without clicking the "Stop recording" button? There are two ways I can imagine achieving this: either disable refreshing (but only in record mode) OR allow for refreshing but have it do nothing (and navigate back to my record mode state).

App.tsx

function App() {
    return (
        <Provider store={store}>
            <ConnectedRouter history={history}>
                <React.Fragment>
                    <Route exact path="/"><Redirect to="/app" /></Route>
                    <Route exact path="/app" component={HomeScreenContainer} />
                </React.Fragment>
            </ConnectedRouter>
        </Provider>
    );
}

export default App;

HomeScreenComponent

export class HomeScreenComponent extends React.PureComponent<HomeScreenProps, FormState> {
    render() {
        return (
            <div>
                <Container>
                    {this.props.mode === SETUP_MODE && <SetupContainer />}
                    {this.props.mode === RECORD_MODE && <RecordingContainer />}
                </Container>
            </div>
        );
    }
}

In my Redux state, the default mode for the application is SETUP_MODE

const defaultState: HomeScreenState = {
    mode: SETUP_MODE,
    ...// other stuff here
};

Any help would be greatly appreciated.

Upvotes: 1

Views: 3172

Answers (3)

Nijat Aliyev
Nijat Aliyev

Reputation: 876

For class components

  componentDidMount() {
    window.addEventListener('beforeunload', this.handleBeforeUnload);
  }

  componentWillUnmount() {
    window.removeEventListener('beforeunload', this.handleBeforeUnload);
  }

  handleBeforeUnload = (event) => {
    const message = "Are you sure you want to leave?";
    event.preventDefault();
    event.returnValue = message;
    return message;
  };

For functional components

 useEffect(() => {
    const handleBeforeUnload = (event) => {
      const message = "Are you sure you want to leave?";
      event.preventDefault();
      event.returnValue = message;
      return message;
    };

    window.addEventListener('beforeunload', handleBeforeUnload);

    return () => {
      window.removeEventListener('beforeunload', handleBeforeUnload);
    };
  }, []);

Upvotes: 0

Baqer Naqvi
Baqer Naqvi

Reputation: 6504

You can not prevent page refresh, but you can show the warning/alert to user if user tries to leave the page with some pending changes.

   if (somePendingChange) {
    window.onbeforeunload = () => true
  } else {
    window.onbeforeunload = undefined
  }

It will show an alert to user if condition is true.

Upvotes: 4

JULIEN PICARD
JULIEN PICARD

Reputation: 1832

I don't think you can prevent the action of refresh from a browser and this not adviced also.

What you can do its store a variable as a cookie or in localStorage in order to be able to know, when the user refresh, if he was on record or setup mode just before the refresh.

Upvotes: 0

Related Questions