diff --git a/packages/dataverse/src/derivations/DerivationEmitter.ts b/packages/dataverse/src/derivations/DerivationEmitter.ts deleted file mode 100644 index e4428fe..0000000 --- a/packages/dataverse/src/derivations/DerivationEmitter.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type Ticker from '../Ticker' -import Emitter from '../utils/Emitter' -import type {default as Tappable} from '../utils/Tappable' -import type {IDerivation} from './IDerivation' - -/** - * An event emitter that emits events on changes to a derivation. - */ -export default class DerivationEmitter { - private _derivation: IDerivation - private _ticker: Ticker - private _emitter: Emitter - private _lastValue: undefined | V - private _lastValueRecorded: boolean - private _hadTappers: boolean - - /** - * @param derivation - The derivation to emit events for. - * @param ticker - The ticker to use to batch events. - */ - constructor(derivation: IDerivation, ticker: Ticker) { - this._derivation = derivation - this._ticker = ticker - this._emitter = new Emitter() - this._emitter.onNumberOfTappersChange(() => { - this._reactToNumberOfTappersChange() - }) - this._hadTappers = false - this._lastValueRecorded = false - this._lastValue = undefined - return this - } - - private _possiblyMarkAsStale = () => { - this._ticker.onThisOrNextTick(this._refresh) - } - - private _reactToNumberOfTappersChange() { - const hasTappers = this._emitter.hasTappers() - if (hasTappers !== this._hadTappers) { - this._hadTappers = hasTappers - if (hasTappers) { - this._derivation.addDependent(this._possiblyMarkAsStale) - } else { - this._derivation.removeDependent(this._possiblyMarkAsStale) - } - } - } - - /** - * The tappable associated with the emitter. You can use it to tap (subscribe to) the underlying derivation. - */ - tappable(): Tappable { - return this._emitter.tappable - } - - private _refresh = () => { - const newValue = this._derivation.getValue() - if (newValue === this._lastValue && this._lastValueRecorded === true) return - this._lastValue = newValue - this._lastValueRecorded = true - this._emitter.emit(newValue) - } -} diff --git a/packages/dataverse/src/derivations/prism/prism.ts b/packages/dataverse/src/derivations/prism/prism.ts index 39a0323..69b973a 100644 --- a/packages/dataverse/src/derivations/prism/prism.ts +++ b/packages/dataverse/src/derivations/prism/prism.ts @@ -1,7 +1,6 @@ import type Ticker from '../../Ticker' import type {$IntentionalAny, VoidFn} from '../../types' import Stack from '../../utils/Stack' -import DerivationEmitter from '../DerivationEmitter' import type {IDerivation} from '../IDerivation' import {isDerivation} from '../IDerivation' import { @@ -200,6 +199,8 @@ class HotHandle { } } +const emptyObject = {} + class PrismDerivation implements IDerivation { /** * Whether the object is a derivation. @@ -227,12 +228,31 @@ class PrismDerivation implements IDerivation { listener: (v: V) => void, immediate: boolean = false, ): VoidFn { - const unsubscribe = new DerivationEmitter(this, ticker) - .tappable() - .tap(listener) - if (immediate) { - listener(this.getValue()) + const dependent = () => { + ticker.onThisOrNextTick(refresh) } + + let lastValue = emptyObject + + const refresh = () => { + const newValue = this.getValue() + if (newValue === lastValue) return + + lastValue = newValue + listener(newValue) + } + + this.addDependent(dependent) + + if (immediate) { + lastValue = this.getValue() + listener(lastValue as $IntentionalAny as V) + } + + const unsubscribe = () => { + this.removeDependent(dependent) + } + return unsubscribe } diff --git a/packages/playground/src/shared/dom/Scene.tsx b/packages/playground/src/shared/dom/Scene.tsx index 576e5bf..e8e35e4 100644 --- a/packages/playground/src/shared/dom/Scene.tsx +++ b/packages/playground/src/shared/dom/Scene.tsx @@ -183,7 +183,7 @@ export const Scene: React.FC<{project: IProject}> = ({project}) => { return studio.onSelectionChange((newState) => { setSelection(newState) }) - }) + }, []) const containerRef = useRef(null!)