Arian
Arian

Reputation: 7719

Clear localStorage onbeforeunload

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

Answers (2)

Geraldo B. Landre
Geraldo B. Landre

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

Oday Fraiwan
Oday Fraiwan

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

Related Questions