Last active
January 5, 2023 23:32
-
-
Save ox/6ed13e7a0b0f265a6996f2ce32010209 to your computer and use it in GitHub Desktop.
Example Lit data store using immer and ulid
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import produce from "https://cdn.jsdelivr.net/npm/immer/+esm"; | |
import { ulid } from "https://unpkg.com/[email protected]/dist/index.esm.js"; | |
// BaseStore is responsible for managing subscribers to the store and | |
// notifying them of changes. | |
class BaseStore { | |
constructor() { | |
this.subscribers = new Set([]); | |
} | |
subscribe(host) { | |
this.subscribers.add(host); | |
} | |
unsubscribe(host) { | |
this.subscribers.delete(host); | |
} | |
updateSubscribers() { | |
this.subscribers.forEach(host => host.requestUpdate()); | |
} | |
} | |
// LocalStorageBackendStore persists the data when subscribers should be notified of changes. | |
// It also allows loading. | |
class LocalStorageBackendStore extends BaseStore { | |
constructor(key) { | |
super(); | |
this.key = key; | |
} | |
persist(data) { | |
localStorage.setItem(this.key, JSON.stringify(data)); | |
} | |
load() { | |
return JSON.parse(localStorage.getItem(this.key)); | |
} | |
updateSubscribers(data) { | |
this.persist(data); | |
super.updateSubscribers(); | |
} | |
} | |
// TasksStore is a store that has localstorage persistence. Very basic CRUD actions | |
class TasksStore extends LocalStorageBackendStore { | |
constructor() { | |
super('tasks'); | |
this.tasks = this.load() || []; | |
} | |
getTasks() { | |
return this.tasks; | |
} | |
getTask(id) { | |
return this.addTasktasks.find(task => task.id === id); | |
} | |
addTask(name, time) { | |
this.tasks = produce(this.tasks, draft => { | |
draft.push({id: ulid(), name, time}); | |
}); | |
this.updateSubscribers(this.tasks); | |
} | |
editTask(id, changes = {}) { | |
this.tasks = produce(this.tasks, draft => { | |
const idx = this.tasks.findIndex(task => task.id === id); | |
if (idx < 0) { | |
return; | |
} | |
Object.assign(draft[idx], changes); | |
}); | |
this.updateSubscribers(this.tasks); | |
} | |
removeTask(id) { | |
this.tasks = produce(this.tasks, draft => { | |
const idx = this.tasks.findIndex(task => task.id === id); | |
if (idx < 0) { | |
return; | |
} | |
draft = draft.splice(idx, 1); | |
}); | |
this.updateSubscribers(this.tasks); | |
} | |
} | |
// The actual data is stored in a singleton here so all LitElements see the same | |
// data and get notified of the same changes. | |
const store = new TasksStore(); | |
// LitElements subscribe to this ReactiveController to receive updates to changes | |
// in the store, as well as make changes so that other elements can see them. | |
export default class TasksControler { | |
constructor(host) { | |
this.host = host; | |
host.addController(this); | |
this.store = store; | |
} | |
hostConnected() { | |
store.subscribe(this.host); | |
} | |
hostDisconnected() { | |
store.unsubscribe(this.host); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment