# Reactive

This package it can be used independently. It is a set of decorators which allows to use ref and computed as class properties and forget about checks like this:

const value = isRef(this.field) ? this.field.value : this.field);

# Installation

# Usage

WARNING

As of TypeScript 4.3, support of experimental decorators must be allowed by the following tsconfig.json options:

{
  "compilerOptions": {
    // ...
    "moduleResolution": "node",
    "useDefineForClassFields": false,
    "experimentalDecorators": true
  }
}

Experimantal decorators are still available as legacyTracked and legacyCalculated.

The package provides two decorators. tracked makes a ref from the class field. calculated wrapps a getter/setter pair and makes a computed property.

DANGER

calculated decorator must be applied to both getter and setter method, whereas legacyCalculated decorator must only be applied to the getter.

WARNING

isRef and toRef functions don't work with decorated fields, but decorated fields are not mutated within reactive objects as a benefit.

Let's look at the trivial example:

You may try to write the following code, but it won't work:

class InvalidClass {
  public num = ref(2);
  public factor = ref(3);
  readonly mul = computed(() => this.num.value * this.factor.value);
}

const invalid = new InvalidClass();

const invalidObj = reactive({ invalid });

invalidObj.invalid.factor = 4;
console.log(invalidObj.invalid.mul);
// Ooops! throws an error, because this.num is a `number`, not `{ value: number }`

The brutal solution:

class MyClass {
  private _num: Ref<number> | number = ref(2);
  private _factor: Ref<number> | number = ref(3);
  private readonly _mul: ComputedRef<number> | number> = computed(() => this.num * this.factor);

  public get num() {
    return isRef(this._num) ? this._num.value : this._num;
  }

  public set num(value: number) {
    isRef(this._num) ? (this._num.value = value) : (this._num = value);
  }

  public get factor() {
    return isRef(this._factor) ? this._factor.value : this._factor;
  }

  public set factor(value: number) {
    return isRef(this._factor) ? (this._factor.value = value) : (this._factor = value);
  }

  public get mul() {
    return isRef(this._mul) ? this._mul.value : this._mul;
  }
}

const my = new MyClass();

const myObj = reactive({ my });

myObj.my.factor = 4;

console.log(myObj.my.mul); // 8 - everything works fine