All files / src/Watch Watch.ts

84.21% Statements 16/19
66.66% Branches 4/6
57.14% Functions 4/7
84.21% Lines 16/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 789x                                   9x   68x     68x     68x     68x                                             68x 68x 68x     68x 68x           7x         128x 125x 125x 125x          
import { bindObserver, destroyWatchers, watchWithScope } from '../helpers'
import type { Destructor, Observer, Reaction, Watcher } from '../types'
 
/**
 * Watcher class for reactive state tracking.
 * Executes callback function when observed states change.
 * @class Watch
 * @implements {Observer}
 *
 * @example
 * // Create state
 * const count = new State(0)
 *
 * // Create watcher that logs the state changes
 * new Watch(() => console.log(count.value)) // auto-subscribes to count
 *
 * count.value = 1 // triggers watcher callback
 */
export class Watch implements Observer {
  /** Whether the watcher has been destroyed */
  destroyed = false
 
  /** Tracks if the computation has run at least once. */
  updated = false
 
  /** Cleanup functions to run when watcher is destroyed */
  readonly destructors = new Set<Destructor>()
 
  /** Child observers created within this watcher's scope */
  readonly children = new Set<Observer>()
 
  // TODO: remove in major release
  /** @deprecated Use `children` */
  get childrenObservers () {
    return this.children
  }
 
  // TODO: remove in major release
  /** @deprecated Use `childrenObservers` */
  get childWatchers () {
    return this.children
  }
 
  // TODO: remove in major release
  /** @deprecated Use `reaction` */
  get watcher () {
    return this.reaction
  }
 
  constructor (reaction: Reaction<void>, freeParent?: boolean, freeUpdate?: boolean)
  /** @deprecated `update` argument is deprecated, use `Reaction` */
  constructor (reaction: Watcher<void>, freeParent?: boolean, freeUpdate?: boolean)
  constructor (readonly reaction: Watcher<void> | Reaction<void>, freeParent?: boolean, freeUpdate?: boolean) {
    Eif (!freeParent) {
      bindObserver(this)
    }
 
    Eif (!freeUpdate) {
      this.update()
    }
  }
 
  /** Destroy watcher and cleanup all dependencies */
  destroy () {
    destroyWatchers(this)
  }
 
  /** Force watcher update regardless of state changes */
  update () {
    if (!this.destroyed) {
      watchWithScope(this, () => {
        this.reaction(this.updated) // TODO: remove `this.updated` in major release
        this.updated = true
      })
    }
  }
}