Last active
September 3, 2023 23:18
-
-
Save Westbrook/bf27c6e5fc66c9c559b8e680ad9648a1 to your computer and use it in GitHub Desktop.
useEffect() for `LitElement`... because everyone's doing it?
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 {LitElement, html} from '@polymer/lit-element'; | |
import {UseEffectMixin} from './use-effect.js'; | |
class MyElement extends UseEffectMixin(LitElement) { | |
static get properties() { | |
return { | |
mood: {type: String}, | |
expression: {type: String} | |
} | |
} | |
constructor() { | |
super(); | |
// useEffect() with set up and cleanup. | |
this.useEffect((props) => { | |
let {mood} = props; | |
console.log('effect', mood); | |
return () => { | |
console.log('cleanup', mood); | |
} | |
}); | |
// useEffect() with a property change gate | |
this.useEffect(() => console.log(this.mood), ['expression']); | |
// useEffect() for firstUpdated() and disconnectedCallback() | |
this.useEffect(() => { | |
console.log('first'); | |
return () => console.log('last'); | |
}, []); | |
} | |
render() { | |
return html` | |
<style> .mood { color: green; } </style> | |
A ${this.expression} sort of ${this.mood}. | |
`; | |
} | |
} |
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
const hasRecentlyConnected = Symbol(); | |
const effects = Symbol(); | |
const cleanups = Symbol(); | |
const cleanupsDisconnected = Symbol(); | |
const cleanup = Symbol(); | |
const UseEffectMixin = (base) => { | |
return class extends base { | |
[effects] = []; | |
[cleanups] = []; | |
[cleanupsDisconnected] = []; | |
connectedCallback() { | |
this[hasRecentlyConnected] = true; | |
super.connectedCallback(); | |
} | |
disconnectedCallback() { | |
super.disconnectedCallback(); | |
this[cleanups] = this[cleanup](this[cleanups]); | |
this[cleanupsDisconnected] = this[cleanup](this[cleanupsDisconnected]); | |
} | |
updated(changedProperties) { | |
super.updated(changedProperties); | |
this[cleanups] = this[cleanup](this[cleanups]); | |
this[effects].map(({effect, tests}) => { | |
if (tests && ((!tests.length && !this[hasRecentlyConnected]) || !tests.every(test => changedProperties.has(test)))) return; | |
const cleanup = effect(this); | |
if (cleanup && (!tests || tests.length)) this[cleanups].push(cleanup); | |
else if (cleanup) this[cleanupsDisconnected].push(cleanup); | |
}); | |
this[hasRecentlyConnected] = false; | |
} | |
[cleanup](cleanups) { | |
cleanups.map(cleanup => cleanup()); | |
return []; | |
} | |
useEffect(effect, tests) { | |
this[effects].push({effect, tests}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment