0

I have a page which in it there is a Webrtc call between users.

And i want that when a user tries to go to another page/reload page/exit browser, there will be a prompt asking him if he's sure that he wants to leave the page, and if the user presses "yes", i want there to be a callback.

In the callback(not sure if relevant) i would close the peers and disconnect everything properly so that the call will get disconnected and the user won't hear audio anymore and the other side will know the user got disconnected also.

  • To do this on refresh i saw the window.onunloaded function

  • Is it even possible on browser exit?

  • I saw the Prompt option to do this on route change but i didn't see how to insert a callback on confirmation there.

I will be happy to get one working example as it feels to complicated for such a little thing which is weird..

Thanks.

1 Answers1

1

Handling React's navigation events

I think what you're looking for is the getUserConfirmation prop of BrowserRouter component.

The function passed to the prop might look like (TypeScript example):

const getUserConfirmation = (
    message: string,
    callback: (ok: boolean) => void
): void => {
    const answer = window.confirm("Do you want to navigate away?");

    // do something depending on which button was pressed

    callback(answer); // allow or disallow React's navigation
};

In the place where you define your routes:

<BrowserRouter getUserConfirmation={getUserConfirmation}>
    ... routes go here ...
</BrowserRouter>

You'll still need to use <Prompt>, though:

<Prompt
     when={boolean}
     message="This string will be supplied in the confirmation function above as second parameter"
/>

Handling browser refresh

You might want to add a callback like this

window.onbeforeunload = () => {
    // some non-blocking logic

    return true;
};

After you no longer need it, you can cleanup:

window.onbeforeunload = null;

Looking at this SO question, it doesn't seem to be possible out of the box to capture the user's response to the native confirm window in onbeforeunload.

Probably window.onunload would be the right place to clean up your stuff as it most probably means the user has opted to leave the page.

Rosen Dimov
  • 1,055
  • 12
  • 32
  • how do i use this with the default modal? because as it is now it doesn't use the default(it doesn't show it) – heapoverflow Jul 14 '20 at 17:27
  • Initially I added the case which covers **React's navigation events**, which don't cover **browser's unload event**. I've made an edit which shows how to subscribe to the unload event and show or not the browser's dialog depending on your logic. – Rosen Dimov Jul 14 '20 at 17:54
  • yea, thank you for that. but what i mean is that whenever i add the `getUserConfirmation` to the `BrowserRouter` properties i don't get the prompt, maybe it overrides the default one? i want the default one but the option to do the cleanup like in your example – heapoverflow Jul 14 '20 at 18:02
  • So you want to open the browser's native prompt both on React navigations and on browser refresh? – Rosen Dimov Jul 14 '20 at 18:09
  • yea, i dont mind how to prompt looks like, what's important is the callback after :) – heapoverflow Jul 14 '20 at 18:16
  • I made another edit. Seems it's possible to do it when doing React navigation (by using ```window.confirm```), but not when you refresh the browser. I added a link to another question that states you can't have a blocking logic in ```onbeforeunload``` event to wait for the answer of the user. I guess ```window.onunload``` would be the place for your cleanup logic on refreshes. – Rosen Dimov Jul 14 '20 at 19:32
  • it works! one last question, can i place the `getUserConfirmation` in the page of the conversation instead of the main page which contains all the components? because the variables that i need for the cleanup are in the second page – heapoverflow Jul 14 '20 at 20:56
  • It can be placed only at the router level. You're either off to using global variables or serializing and passing them via the message prop of ``````, but that would work only for React navigation and looks rather hacky. Global variables (well not trully global, but rather application-wide global) would handle both cases, you can also add some additional layer when you store those variables (like service classes or so, there are no dependency injection options out of the box in React). – Rosen Dimov Jul 15 '20 at 08:05