History: QuotaExceededError in Safari incognito mode

Created on 10 Sep 2015  路  4Comments  路  Source: ReactTraining/history

When using safari in incognito mode, navigation fails with the following exception:

QuotaExceededError: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota.

Safari denies usage of local/session storages when in incognito mode, and raises this error when you try to.

I am using the BrowserHistory history and it seems like the error stems from history/DOMStateStorage.

possible bug

Most helpful comment

You can use this pollyfill to use the localStorage in memory:

(function () {
  function isSupported() {
    var item = 'localStoragePollyfill';
    try {
      localStorage.setItem(item, item);
      localStorage.removeItem(item);
      return true;
    } catch (e) {
      return false;
    }
  }

  if (!isSupported()) {
    try {
      Storage.prototype._data = {};

      Storage.prototype.setItem = function (id, val) {
        return this._data[id] = String(val);
      };

      Storage.prototype.getItem = function (id) {
        return this._data.hasOwnProperty(id) ? this._data[id] : undefined;
      },

      Storage.prototype.removeItem = function (id) {
        return delete this._data[id];
      },

      Storage.prototype.clear = function () {
        return this._data = {};
      }
    } catch (e) {
      console.error('localStorage pollyfill error: ', e);
    }
  }
}());

All 4 comments

Thanks for reporting this bug, @AndreasHogstrom :)

The solution is probably two-fold:

  1. We should catch the QuotaExceededError and emit a warning instead
  2. We should make sure we are only ever calling saveState when we actually need to (i.e. when there is some state to save, e.g. a call to pushState(null, '/path') shouldn't actually try to saveState)

I think that would give developers the flexibility they need to either a) use state and ignore the warnings for users in incognito mode (or possibly try to detect when someone is in incognito mode and do the right thing) or 2) avoid using state entirely, thereby avoiding the warnings.

Would you care to make a PR @AndreasHogstrom?

@mjackson I ran into this today, does a simple in memory storage that polyfill the localStorage can make the trick?

I can drop you a PR with warning emitting for now.

You can use this pollyfill to use the localStorage in memory:

(function () {
  function isSupported() {
    var item = 'localStoragePollyfill';
    try {
      localStorage.setItem(item, item);
      localStorage.removeItem(item);
      return true;
    } catch (e) {
      return false;
    }
  }

  if (!isSupported()) {
    try {
      Storage.prototype._data = {};

      Storage.prototype.setItem = function (id, val) {
        return this._data[id] = String(val);
      };

      Storage.prototype.getItem = function (id) {
        return this._data.hasOwnProperty(id) ? this._data[id] : undefined;
      },

      Storage.prototype.removeItem = function (id) {
        return delete this._data[id];
      },

      Storage.prototype.clear = function () {
        return this._data = {};
      }
    } catch (e) {
      console.error('localStorage pollyfill error: ', e);
    }
  }
}());

Yeah ! Finally I get the solution here~

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andi5 picture andi5  路  6Comments

johnjesse picture johnjesse  路  6Comments

mereskin-zz picture mereskin-zz  路  4Comments

richardgorman picture richardgorman  路  5Comments

mgustin12 picture mgustin12  路  5Comments