Skip to content

Latest commit

 

History

History
43 lines (32 loc) · 3.41 KB

objects.md

File metadata and controls

43 lines (32 loc) · 3.41 KB

Objects

  • Objects are deeply reactive by default in the following cases:
    • When assigned to a reactive variable
    • When added to a deeply reactive object (e.g. as the value of an object property, into an Array or Set, or as the value of a Map key)

Getters and setters

  • While get syntax is supported, it's not always reactive. As a result, it can be a common source of bugs and should be avoided if possible.
    • If you must use it, you should avoid referencing any reactive values except for those in the object itself (e.g. using this.foo). In fact, you should even avoid accessing this.foo.bar in a getter, since only this.foo will be reactive. This is a limitation of Valtio.
  • Similarly, set syntax is supported. There's nothing inherently dangerous with set syntax, but it should be used sparingly due to get syntax being so problematic.
  • As a reminder, you don't need (and shouldn't use) get syntax to expose a reactive variable to the outside world. Just assign the variable to a property of the returned object literal, and it will still be reactive. If that doesn't work for your use case, you should use a computed binding instead.

Gotchas

  • It's not possible to subscribe only to the "keys" or "indices" of a reactive object, array, etc. For example, using Object.keys on a reactive object within a computed or watch callback will subscribe to the object's keys and values. This means your callback will re-run when a key's value changes, even though you may only care about the keys themselves. This is a limitation of Valtio. If you're doing expensive computations, you'll want to keep a reference to the previous keys for comparison and bail out when the keys haven't changed.

Subscribing to changes

  • Like with reactive variables, accessing a property of a reactive object within a computed or watch callback will subscribe to changes in that property.
    • Importantly, referencing a reactive object within computed or watch will subscribe to all properties of that object, unless you access a specific property. The same is true for Array, Map, and Set objects, as well as nested objects.
  • You can deeply subscribe to changes in an object with the subscribe function.
    subscribe(obj, () => console.log('something in obj changed'))
    • Your callback receives an array of operations that were performed on the object, but this API is not yet stable and may change in the future.
  • You can subscribe to a single property of an object with the subscribeKey function.
    subscribeKey(obj, 'foo', () => console.log('foo changed'))
    • If the property points to an object, that object will not be subscribed to. Only the property itself will be subscribed to.
const obj = { a: 1, b: { c: 2 } }

// Deeply subscribe to changes in an object.
subscribe(obj, () => console.log('something in obj changed'))

// Subscribe to changes in a single property of an object.
subscribeKey(obj, 'a', () => console.log('a changed'))

watch(() => {
  obj // Deeply subscribe to changes in `obj`
  obj.a // Subscribe to changes in `obj.a` only
  obj.b.c // Subscribe to changes in `obj.b.c` only
})