javascriptvue.jsvuejs3vue-composition-api

How to update reactive object without losing reactivity (vue3 compositionAPI)


I tried to update a reactive object, but reactivity is lost.

How to solve this problem?

const obj = reactive({ id:0, name: "Tom" })

const updateObj = { id:1, name: "Bob" }

Object.keys(updateObj).forEach(key => {
   obj[key] = updateObj[key]
 })

console.log(isRef(obj.id)) // => false

Solution

  • Actually your example should work, when it comes to reactivity. Instead of iterating through the keys, it might be a better idea to simply use Object.assign(obj, updateObj), but your approach should work as well.

    But, it seems you have a slight misconception about reactivity and the isRef function: isRef does not check if the given argument is reactive, but specifically if it is a ref object (see this section in the Vue docs). There is also a function called isReactive that can check specifically, if an object is a reactive object (see here). Note, that this does also not return true for the property of a reactive object.

    I've created a small example, that should illustrate the difference between the two methods. It also shows, that reactivity works, even if the isRef and isReactive functions both return false:

    <script setup>
    import { computed, reactive, ref, isReactive, isRef } from 'vue';
      
    const obj = reactive({ id: 0 , name: "Tom" })
    const realRef = ref('foo')
    
    const isRefOrReactive = computed(() => ({
      objRef: isRef(obj),
      objReactive: isReactive(obj),
      objIdRef: isRef(obj.id),
      objIdReactive: isReactive(obj.id),
      refRef: isRef(realRef),
      refReactive: isReactive(realRef)
    }))
    
    const updateObject = () => {
      const updateObj = { id: 1 , name: "Bob" }
      Object.keys(updateObj).forEach(key => {
        obj[key] = updateObj[key]
      })
      // Object.assign(obj, updatedObj)
    }
    </script>
    
    <template>
      <pre>{{ obj }}</pre>
      <pre>{{ obj.name }}</pre>
      <pre>{{ isRefOrReactive }}</pre>
      <button @click="updateObject">
        Swap data
      </button>
    </template>