All files index.ts

100% Statements 50/50
92.86% Branches 26/28
100% Functions 9/9
100% Lines 47/47

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 741x 1x 1x   1x 1x         13x 13x 11x 11x 4x 4x 4x 4x 4x 2x 2x 2x       4x   20x 20x 20x 8x   12x 12x   12x 21x 12x 9x 8x 8x 8x         20x   11x   6x 6x 6x   6x 10x 4x   6x     6x 4x 4x   6x         1x 1x 1x  
import {Watch, Cache, getDecors, unwatch} from 'watch-state'
import {Mixer} from '@watch-state/mixer'
import {useEffect, useState, FunctionComponent, Component} from 'react'
 
export const WATCHER = Symbol('watcher')
export const UPDATING = Symbol('watcher')
 
type Target = FunctionComponent | Component['constructor']
 
function watch <T extends Target> (target: T): T {
  const originalRender = target.prototype?.render
  if (originalRender) {
    const originalComponentWillUnmount = target.prototype.componentWillUnmount
    target.prototype.componentWillUnmount = function componentWillUnmount () {
      this[WATCHER].destructor()
      this[WATCHER] = undefined
      const values = getDecors(this)
      Eif (values) {
        for (const key in values) {
          const value = values[key]
          Eif (value instanceof Cache || value instanceof Mixer) {
            value.destructor()
          }
        }
      }
      originalComponentWillUnmount?.apply(this, arguments)
    }
    target.prototype.render = function render () {
      let result, args = arguments
      if (this[UPDATING]) {
        result = originalRender.apply(this, args)
      } else {
        this[WATCHER]?.destructor()
        unwatch(() => {
          let watcher
          watcher = this[WATCHER] = new Watch(update => {
            if (!update) {
              result = originalRender.apply(this, args)
            } else if (watcher === this[WATCHER]) {
              this[UPDATING] = true
              this.forceUpdate()
              this[UPDATING] = false
            }
          })
        })
      }
      return result
    }
    return target
  } else {
    return function Component () {
      const setValue = useState({})[1]
      const args = arguments
      let result
      let watcher = new Watch(update => {
        if (update) {
          setValue({})
        } else {
          result = target.apply(this, args)
        }
      })
      useEffect(() => () => {
        watcher.destructor()
        watcher = undefined
      })
      return result
    } as unknown as T
  }
}
 
export default watch
export * from 'watch-state'
export * from '@watch-state/mixer'