Vue.js 3 - replace/update reactive object without losing reactivity

Viewed 20203

I need to update a reactive object with some data after fetching:

  setup(){
    const formData = reactive({})

    onMounted(() => {
      fetchData().then((data) => {
        if (data) {
          formData = data //how can i replace the whole reactive object?
        }
      })
    })
  }

formData = data will not work and also formData = { ...formdata, data }

Is there a better way to do this?

3 Answers

Though Boussadjra Brahim's solution works its not the exact answer to the question.

In the sense that reactive data can not be reassigned with = but there is a way to reassign the reactive data. It is Object.assign.

Therefore this should work

    setup(){
        const formData = reactive({})
    
        onMounted(() => {
          fetchData().then((data) => {
            if (data) {
              Object.assign(formData, data) // equivalent to reassign 
            }
          })
        })
      }

Note:

This solution works when your reactive object is empty or always contains same keys.

However, if for example, formData has key x and data does not have key x then after Object.assign, formData will still have key x, so this is not strictly reassigning.

demo example; including watch

According to the official docs :

Since Vue's reactivity tracking works over property access, we must always keep the same reference to the reactive object. This means we can't easily "replace" a reactive object because the reactivity connection to the first reference is lost

reactive should define a state with nested fields that could be mutated like :

 setup(){
    const data= reactive({formData :null })

    onMounted(() => {
      fetchData().then((data) => {
        if (data) {
          data.formData = data 
        }
      })
    })

  }

or use ref if you just have one nested field:

  setup(){
    const formData = ref({})

    onMounted(() => {
      fetchData().then((data) => {
        if (data) {
          formData.value = data 
        }
      })
    })

  }

I guess:

formData = reactive(newObject)
Related