'Whats the difference between @observable and @observable.ref modifiers in mobx?

Mobx supports both @observable and @observable.ref modifiers and their official doc says

observable: This is the default modifier, used by any observable. It clones and converts any (not yet observable) array, Map or plain object into it's observable counterpart upon assignment to the given property

observable.ref: Disables automatic observable conversion, just creates an observable reference instead.

I do not understand why would we need to create a observable reference for an already existing observable. How are these two different and what are their use cases ?



Solution 1:[1]

observable.ref will only track reference changes to the object, which means that you will need to change the whole object in order to trigger the reaction. So if you, for example, have an observable array that is tracked by reference, the contents of the array will not be tracked. Also if you add items to the array that change will also not be tracked.

import { observable, reaction } from "mobx";

const test = observable(
  {
    reference: [{ id: 1 }]
  },
  {
    reference: observable.ref
  }
);

reaction(
  () => {
    return test.reference.length;
  },
  () => {
    console.log("Reaction 1: reference length changed");
  }
);
reaction(
  () => {
    return test.reference[0];
  },
  () => {
    console.log("Reaction 2: reference item changed");
  }
);

test.reference[0] = { id: 2 }; // this will not trigger the reactions
test.reference.push({ id: 3 }); // this will not trigger the reactions
test.reference.pop(); // this will not trigger the reactions

test.reference = []; // this will trigger both reactions

code sandbox example

Solution 2:[2]

I'd like to explain the Ivan V.'s answer. In his code, test.reference is a reference which will not change the address of the variable in the memory until reassign. operations like push/pop or edit the value of test.reference[0] just change the value instead of the variable's reference. So when using the @observable.ref, mobx will compare the memory address of the variable which is observed.But when using the @observable, mobx will compare the variable's value to decide to trigger the reactions.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ivan V.
Solution 2 verakidann