Tasha Herber
Tasha Herber

Reputation: 319

observe localstorage changes in js

I have a single-page app in which I need to react on every change in localstorage, it looks something like:

MyComponent {
    someFuncWhichIsCalledEveryTimeWhenLocalStorageChanges() {
        console.log('local storage changed!');
    }
    
    funcThatChangesLocalStorage() {
        localstorage.setItem('key',val);
        localstorage.getItem('key')
    }
}

And I've tried to use localstorage event:

window.addEventListener('storage', function(event) {
   ...
});

but that didn't work... so I'm thinking about using Observable<>, just don't know how to implement it properly.

Upvotes: 28

Views: 53641

Answers (7)

GMKHussain
GMKHussain

Reputation: 4671

Simplified solution !

const localStore = localStorage.setItem;

localStorage.setItem = function(key, value) {
  const event = new Event('localUpdated');
        event.key = key; 
        event.value = value; 
  
  document.dispatchEvent(event);
  localStore.apply(this, arguments);
};

const localStoreHandler = function(e) {
  console.log(`👉 localStorage.set('${e.key}', '${e.value}') updated`);
};

document.addEventListener("localUpdated", localStoreHandler, false);


localStorage.setItem('username', 'amoos');

// After 2 second
setTimeout( ()=>  localStorage.setItem('username', 'rifat'), 2000)

Upvotes: 8

Yangshun Tay
Yangshun Tay

Reputation: 53119

Huge caveat from the MDN docs: Window storage event:

[window.addEventListener('storage', ...)] won't work on the same page that is making the changes — it is really a way for other pages on the domain using the storage to sync any changes that are made.

So that's probably why it didn't work for you (and for me as well) - you were trying to respond to this listener on other parts of the same page.

Upvotes: 50

Dmitry Kovganov
Dmitry Kovganov

Reputation: 173

You can use a function that makes proxy methods on an object

function watchAnyObject(
  object = {},
  methods = [],
  callbackBefore = function () {},
  callbackAfter = function () {},
) {
  for (let method of methods) {
    const original = object[method].bind(object);
    const newMethod = function (...args) {
      callbackBefore(method, ...args);
      const result = original.apply(null, args);
      callbackAfter(method, ...args);
      return result;
    };
    object[method] = newMethod.bind(object);
  }
}

and use it like this

watchAnyObject(
  window.localStorage,
  ['setItem', 'getItem', 'removeItem'],
  (method, key, ...args) =>
    console.log(`call ${method} with key ${key} and args ${args}`),
);

you can add your listener someFuncWhichIsCalledEveryTimeWhenLocalStorageChanges in the component constructor

constructor() {
  watchAnyObject(window.localStorage, ['setItem', 'getItem', 'removeItem'], this.someFuncWhichIsCalledEveryTimeWhenLocalStorageChanges);
}

Upvotes: 12

Shuang Li
Shuang Li

Reputation: 1

If you want to listen the storage change event in the same document, you can add a storage changed event emit function just like below. When you use localStorage.setItem("xx", "xx"), and trigger this function after it, you will detect the event~

export function emitStorageChangedEvent() {
  const iframeEl = document.createElement("iframe");
  iframeEl.style.display = "none";
  document.body.appendChild(iframeEl);

  iframeEl.contentWindow?.localStorage.setItem("t", Date.now().toString());
  iframeEl.remove();
}

Upvotes: 0

Mac
Mac

Reputation: 1566

The localDataStorage interface (a handy wrapper for the HTML5 localStorage API) conveniently fires change events on the same page/tab/window in which the storage event occurred. Disclaimer: I am the author of the interface.

Once you install localDataStorage, this sample code will let you see those change events:

function nowICanSeeLocalStorageChangeEvents( e ) {
    console.log(
        "subscriber: "    + e.currentTarget.nodeName + "\n" +
        "timestamp: "     + e.detail.timestamp + " (" + new Date( e.detail.timestamp ) + ")" + "\n" +
        "prefix: "        + e.detail.prefix    + "\n" +
        "message: "       + e.detail.message   + "\n" +
        "method: "        + e.detail.method    + "\n" +
        "key: "           + e.detail.key       + "\n" +
        "old value: "     + e.detail.oldval    + "\n" +
        "new value: "     + e.detail.newval    + "\n" +
        "old data type: " + e.detail.oldtype   + "\n" +
        "new data type: " + e.detail.newtype
    );
};
document.addEventListener(
    "localDataStorage"
    , nowICanSeeLocalStorageChangeEvents
    , false
);

Upvotes: 9

XXLIVE
XXLIVE

Reputation: 156

The storage event fires when a storage area (localStorage or sessionStorage) has been modified in the context of another document.

https://developer.mozilla.org/en-US/docs/Web/Events/storage

Upvotes: 0

Charles Stover
Charles Stover

Reputation: 1148

window.addEventListener('storage', ...) works

Make sure you are using the correct event properties.

Here is a basic example of the event listener.

Upvotes: -2

Related Questions