Skip to content

Instantly share code, notes, and snippets.

@motss
Last active January 14, 2023 21:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save motss/d89a5ccb056e42e6d283363c0a6a9f57 to your computer and use it in GitHub Desktop.
Save motss/d89a5ccb056e42e6d283363c0a6a9f57 to your computer and use it in GitHub Desktop.
Best of both worlds: lit-element + mobx
import { html, LitElement } from 'https://unpkg.com/lit-element@latest/lit-element.js?module';
import { observable, action, autorun, reaction } from 'https://unpkg.com/mobx@latest/lib/mobx.es6.js?module';
const store = observable({
title: 'Hello, World!',
count: 0,
incrementCount: action(() => {
store.count += 1;
}),
});
/** [DEBUG]: Inspect store values */
autorun(() => {
console.log('store', { ...store });
});
class MyElement extends LitElement {
static get properties() {
return {
count: { type: Number },
title: { type: String },
};
}
constructor() {
super();
reaction(
() => [store.count, store.title],
([count, title]) => {
this.count = count;
this.title = title;
},
{ fireImmediately: true }
);
}
render() {
return html`
<h1>${this.title}</h1>
<button @click="${this._incrementCount}">Click Me | ${this.count}</button>
`;
}
_incrementCount() {
store.incrementCount();
}
}
window.customElements.define('my-element', MyElement);
import { html, LitElement } from 'https://unpkg.com/lit-element@latest/lit-element.js?module';
import { observable, action, autorun, reaction } from 'https://unpkg.com/mobx@latest/lib/mobx.es6.js?module';
const version = 'test::v0::local_state';
const lc = window.localStorage;
const savedState = lc.getItem(version);
const store = observable({
title: 'Hello, World!',
count: 0,
incrementCount: action(() => {
store.count += 1;
}),
...JSON.parse(savedState),
});
/** [DEBUG]: Log latest states and save states in localStorage */
autorun(() => {
const states = { ...store };
const toBeSaved = Object.keys(states).reduce((p, n) => {
const val = states[n];
if ('function' === typeof(val)) return p;
p[n] = val;
return p;
}, {});
console.log('store', toBeSaved, lc.getItem(version));
lc.setItem(version, JSON.stringify(toBeSaved));
});
class MyElement extends LitElement {
static get properties() {
return {
count: { type: Number },
title: { type: String },
};
}
constructor() {
super();
reaction(
() => [store.count, store.title],
([count, title]) => {
this.count = count;
this.title = title;
},
{ fireImmediately: true }
);
}
render() {
return html`
<h1>${this.title}</h1>
<button @click="${this._incrementCount}">Click Me | ${this.count}</button>
`;
}
_incrementCount() {
store.incrementCount();
}
}
window.customElements.define('my-element', MyElement);
import { html, LitElement } from 'https://unpkg.com/lit-element@latest/lit-element.js?module';
import { observable, action, autorun, reaction } from 'https://unpkg.com/mobx@latest/lib/mobx.es6.js?module';
const store = observable({
title: 'Hello, World!',
count: 0,
updateTitle(title) {
this.title = title;
},
incrementCount() {
console.log('ic');
this.count += 1;
},
resetCount() {
console.log('rc');
this.count = 0;
}
});
const mobxify = superclass => {
return class extends superclass {
connectedCallback() {
super.connectedCallback();
autorun(() => this.storeUpdated());
}
storeUpdated() {}
};
};
class MyElement extends mobxify(LitElement) {
storeUpdated() {
this.title = store.title;
this.count = store.count;
this.requestUpdate();
}
render() {
return html`
<h1>${this.title}</h1>
<button @click="${this._click}">
<span>Current count is ${this.count}</span>
</button>
<button @click="${this._reset}">Reset count</button>
<button @click="${this._updateTitle}">Update title</button>
`;
}
_click() {
store.incrementCount();
}
_reset() {
store.resetCount();
}
_updateTitle() {
const rng = Math.random();
const randTitle = Math.floor(rng * 2) ? rng.toString(16).slice(-7) : 'Hello, World!';
store.updateTitle(randTitle);
}
}
window.customElements.define('my-element', MyElement);
class MyElement2 extends mobxify(LitElement) {
storeUpdated() {
this.title = store.title;
this.requestUpdate();
}
render() {
console.log('myelement2::render');
return html`
<h1>${this.title}</h1>
`;
}
}
window.customElements.define('my-element2', MyElement2);
@motss
Copy link
Author

motss commented May 31, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment