Last active
January 28, 2022 07:24
-
-
Save darthtrevino/a0f00fbfd3cd95e4c6086356ee5172c5 to your computer and use it in GitHub Desktop.
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
type Unsubscribe = () => void | |
type EffectId = string | symbol | |
type EffectFn = () => Unsubscribe | undefined | |
class SideEffects implements ReactiveController { | |
private effectDeps: Record<EffectId, unknown[]> = {} | |
private effectUnsubscribes: Record<EffectId, Unsubscribe | undefined> = {} | |
public constructor(private host: ReactiveControllerHost & Element) { | |
this.host.addController(this); | |
} | |
public useEffect(id: EffectId, effect: EffectFn, deps: unknown[]) { | |
if (this.shouldEffectRun(deps, this.effectDeps[id])) { | |
// invoke old cleanups | |
const prevUnsubscribe = this.effectUnsubscribes[id] | |
if (prevUnsubscribe) { | |
prevUnsubscribe() | |
this.effectUnsubscribes[id] = undefined | |
} | |
// run the effect | |
const unsubscribe = effect() | |
if (unsubscribe) { | |
this.effectUnsubscribes[id] = unsubscribe | |
} | |
} | |
} | |
public hostConnected() { | |
this.clear() | |
} | |
public hostDisconnected() { | |
Object.values(this.effectUnsubscribes).forEach(u => u()) | |
this.clear() | |
} | |
private clear() { | |
this.effectDeps = {} | |
this.effectUnsubscribes = {} | |
} | |
private shouldEffectRun(currDeps: unknown[], prevDeps: unknown[]): boolean { | |
if (!prevDeps) return true | |
if (currDeps.length !== prevDeps.length) throw new Error('effect dependency length should not change'); | |
return currDeps.every((value, idx)=> prevDeps[idx] === value) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment