Reputation: 7719
I'm working with localStorage and I want to change a counter when closing the page.
I found that onbeforeunload
is the event which can be useful, so I decided to call my function in it. (onunload
doesn't work for me in firefox/chrome)
But when I try to call a function , it doesn't do anything.
Is there any way to call a function when closing/refreshing a tab ?
class MyLib{
constructor(){
window.onbeforeunload = function() {
this._onClosePage();
};
}
_onClosePage() {
let openWindowsCount = this._getItem('countOpenWindow');
openWindowsCount--;
if (openWindowsCount === 0) {
this._clearUp();
}
}
_clearUp() {
this._removeItem('countPagesVisited');
}
}
UPDATE
As suggested by Oday , I fixed the binding. But now , it works randomly.
In chrome, it doesn't catch the refresh event, but sometimes it catches the exit.
In firefox, it catches the exit, and randomly catches the refresh.
class MyLib{
constructor(){
document.getElementsByTagName('body')[0].onbeforeunload = this._onClosePage.bind(this);
}
_onClosePage() {
let openWindowsCount = this._getItem('countOpenWindow');
openWindowsCount--;
if (openWindowsCount === 0) {
this._clearUp();
}
}
_onClosePage() { // call it once the page is closed or refreshed
let openWindowsCount = localStorage.getItem('countOpenWindow');
openWindowsCount--;
localStorage.setItem('countOpenWindow' , openWindowsCount);
if (openWindowsCount === 0) {
this._clearUp();
}
}
_clearUp() {
localStorage.removeItem('countOpenWindow');
}
}
Upvotes: 2
Views: 4098
Reputation: 132
In order to clean the localStorage
on beforeunload
, instead of using window.onbeforeunload
directly, you should use the window.addEventListener()
method to start listening to beforeunload
event. This also allows you to remove the event listener when you find fit.
See this explanation on Mozilla Developers Documentation:
Binding to this event can be used to prevent the browser from fully caching the page in cases where content is rendered by javascript. In certain circumstances when returning to a page that has executed javascript in order to populate content, you may find the javascript not running upon the return visit when navigating back. If window.onbeforeunload has been bound (and thus triggered when leaving that page) javascript in the page will be triggered on the subsequent return visit and therefore update the content.
Full text here: https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload
This is probably the reason for the randomness you mentioned.
As an example, see above React component that adds the event listener when it finishes mounting, and than, when it is unmounted it removes the event listener. It is a very elementary example, but I tested it on Firefox 60, Chrome 69 canary, Safari 11.1 and it worked properly.
import React, { Component } from 'react'
class App extends Component {
constructor(props) {
super(props)
this.handleLoad = this.handleLoad.bind(this)
this.handleBeforeunload = this.handleBeforeunload.bind(this)
}
componentDidMount() {
this.handleLoad()
window.addEventListener('beforeunload', this.handleBeforeunload)
}
componentWillUnmount() {
window.removeEventListener('beforeunload', this.handleBeforeunload)
}
render() {
return (
<div className="App">
<p>
Hello World!
</p>
</div>
)
}
handleLoad() {
let countOpenWindow = parseInt(localStorage.getItem('countOpenWindow'), 10)
if (!countOpenWindow) {
countOpenWindow = 0
}
localStorage.setItem('countOpenWindow', ++countOpenWindow)
}
handleBeforeunload() {
let countOpenWindow = parseInt(localStorage.getItem('countOpenWindow'), 10)
if (countOpenWindow > 1) {
localStorage.setItem('countOpenWindow', --countOpenWindow)
} else {
localStorage.removeItem('countOpenWindow')
}
}
}
export default App
Upvotes: 3
Reputation: 1157
You need to capture the context of your class inside the onbeforeunload event handler. Currently, the 'this' refers to the window which fires the event.
constructor(){
let that = this;
window.onbeforeunload = function() {
that._onClosePage();
};
}
Upvotes: 1