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}); } } }