Reactivity Fundamentals

    reactive is the equivalent of the Vue.observable() API in Vue 2.x, renamed to avoid confusion with RxJS observables. Here, the returned state is a reactive object. The reactive conversion is “deep” - it affects all nested properties of the passed object.

    The essential use case for reactive state in Vue is that we can use it during render. Thanks to dependency tracking, the view automatically updates when reactive state changes.

    This is the very essence of Vue’s reactivity system. When you return an object from data() in a component, it is internally made reactive by reactive(). The template is compiled into a render function that makes use of these reactive properties.

    You can learn more about reactive in the section

    1. import { ref } from 'vue'
    2. const count = ref(0)

    ref will return a reactive and mutable object that serves as a reactive reference to the internal value it is holding - that’s where the name comes from. This object contains the only one property named value:

    1. import { ref } from 'vue'
    2. const count = ref(0)
    3. console.log(count.value) // 0
    4. count.value++
    5. console.log(count.value) // 1

    When a ref is returned as a property on the render context (the object returned from setup()) and accessed in the template, it automatically unwraps to the inner value. There is no need to append .value in the template:

    Access in Reactive Objects

    When a ref is accessed or mutated as a property of a reactive object, it automatically unwraps to the inner value so it behaves like a normal property:

    1. count
    2. })
    3. console.log(state.count) // 0
    4. state.count = 1
    5. console.log(count.value) // 1

    If a new ref is assigned to a property linked to an existing ref, it will replace the old ref:

    1. const otherCount = ref(2)
    2. state.count = otherCount
    3. console.log(state.count) // 2
    4. console.log(count.value) // 1

    When we want to use a few properties of the large reactive object, it could be tempting to use ES6 destructuring to get properties we want:

    1. import { reactive } from 'vue'
    2. const book = reactive({
    3. author: 'Vue Team',
    4. year: '2020',
    5. description: 'You are reading this book right now ;)',
    6. price: 'free'
    7. })
    8. let { author, title } = book

    Unfortunately, with such a destructuring the reactivity for both properties would be lost. For such case, we need to convert our reactive object to a set of refs. These refs will retaining the reactive connection to the source object:

    1. import { reactive, toRefs } from 'vue'
    2. const book = reactive({
    3. author: 'Vue Team',
    4. year: '2020',
    5. title: 'Vue 3 Guide',
    6. description: 'You are reading this book right now ;)',
    7. price: 'free'
    8. })
    9. let { author, title } = toRefs(book)
    10. console.log(book.title) // 'Vue 3 Detailed Guide'

    You can learn more about refs in the section

    Sometimes we want to track changes of the reactive object ( or reactive) but we also want prevent changing it from a certain place of the application. For example, when we have a provided reactive object, we want to prevent mutating it where it’s injected. To do so, we can create a readonly proxy to the original object: