Skip to content

Instantly share code, notes, and snippets.

@md-riaz
Created April 30, 2024 10:04
Show Gist options
  • Save md-riaz/1857e3b084c6a4c8da1f53d8da5dca46 to your computer and use it in GitHub Desktop.
Save md-riaz/1857e3b084c6a4c8da1f53d8da5dca46 to your computer and use it in GitHub Desktop.
function getLocalStorage() {
try {
return window.localStorage;
} catch (_) {
const store = {};
return {
getItem(name) {
return store[name] || null;
},
setItem(name, val) {
store[name] = val;
},
};
}
}
const localStorage = getLocalStorage();
class Store {
constructor(initialState, {
localStorageKey = 'store',
dontPersist = [],
} = {}) {
this.events = {};
this.localStorageKey = localStorageKey;
this.dontPersist = dontPersist;
let storedState;
try {
const stored = localStorage.getItem(this.localStorageKey);
storedState = stored ? JSON.parse(stored) : {};
} catch (e) {
storedState = {};
} finally {
storedState = typeof storedState === 'object' ? storedState : {};
}
this._state = { ...initialState, ...storedState };
window.addEventListener('storage', (e) => {
// Cross-tab communication
if (e.key !== this.localStorageKey) {
return;
}
if (!e.newValue) {
// The localStorage has been removed
return location.reload();
}
const storedState = JSON.parse(e.newValue);
this.setStoredState(storedState);
this.emit('storageSynced');
});
}
get state() {
return this._state;
}
persist() {
const persistable = { ...this._state };
for (const ignoredKey of this.dontPersist) {
delete persistable[ignoredKey];
}
localStorage.setItem(this.localStorageKey, JSON.stringify(persistable));
}
setState(partialState) {
const prevState = this._state;
this._state = { ...prevState, ...partialState };
this.persist();
this.emit('change', [this._state, prevState, partialState]);
}
unsetSinglePropInStateByName(propName) {
const prevState = this._state;
delete prevState[propName];
this._state = { ...prevState };
this.persist();
this.emit('change', [this._state, prevState]);
}
setStoredState(storedState) {
const prevState = this._state;
const nonPeristable = {};
for (const ignoredKey of this.dontPersist) {
nonPeristable[ignoredKey] = prevState[ignoredKey];
}
this._state = { ...storedState, ...nonPeristable };
this.emit('change', [this._state, prevState]);
}
on(event, listener) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
}
emit(event, args) {
if (this.events[event]) {
this.events[event].forEach(listener => {
listener.apply(null, args);
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment