Run function only when tab/window is actually closed

Viewed 666

I am trying to send a get request to express from a react client when the user closes the tab.

I actually managed it with this, but with no confirmation:

window.addEventListener('beforeunload', async () => await axios('/delete');

If I try to make use of the proper confirmation message:

window.addEventListener('beforeunload', (e) => {
  e.preventDefault();
  e.returnValue = '';
  return true;
})

I do get the confirmation message, but I have no way to capture the response to run the function only if leave is clicked.

I saw a lot of responses about this but they are very old and dont seem to work on the latest browsers.

2 Answers

use useEffectcallback which gets called on component unmount , so in your route component use this .

useEffect (()=>{
  
  return ()=>{
  //your code here , make sure its not updating any state variable    
  }
}
,[])

In the end I did something really convoluted. But it works for me.

On the React front end, I make the call to delete as soon as the event is triggered. Since I can not detect if the user clicks to stay, I do setTimeout and give it 1s on the front end.

useEffect(() => window.addEventListener('beforeunload', async (e) => {
  e.preventDefault()
  e.returnValue = ''
  await axios.post('/api/delete', { stay: false })
  setTimeout(async () => {
   await axios.post('/api/delete', { stay: true })
  }, 1000)
 }), [])

And on the Express back end, I wait 2s for a cancellation to occur, if not then go ahead and delete.

let timer

app.post('/api/delete', (req, res) => {
  if (req.body.stay) {
    clearTimeout(timer)
  } else {
    clearTimeout(timer)
    timer = setTimeout(() => console.log('delete a file here'), 2000)
  }
  res.end()
})

If anyone can come up with something better I will accept that answer.

Related