1

Just started using Vue composition-api (with Vue2) and I ran into some reactivity? problem.

In the template, I want to render list of elements based on selected date.

My template:

...
<div v-for="(act, idx) in elementsPerDay[dateMatchable]" :key="idx">
   ...some content...
</div>
...

Now the problem is that when the component is created and data are fetched, nothing is rendered and elementsPerDay are empty (in the template). Once I force template update (for example by calling vm.$forceUpdate()) everything works fine.

My setup:

...
const selectedDate = new Date()
const { data } = <async function to get data>
const dateMatchable = computed(() => formatDate(selectedDate, 'YYYY-MM-DD')) // returns selectedDate as YYYY-MM-DD

// Here I init my reactive object
const elementsPerDay = reactive({})

// Here I fill my elementsPerDay when data changes (basically grouping data by day)
watch(data, e => {
  const elsPerDay = {}

  for (let idx = 0; idx < data.length; idx++) {
    const element = data[idx]
    const elementDate = formatDate(data.datetime, 'YYYY-MM-DD')

    if (elementsPerDay[elementDate] === undefined) {
      elsPerDay[elementDate] = []
    }

    elsPerDay[elementDate].push(act)
  })
  
  // Assign data to my reactive object
  Object.assign(elementsPerDay, elsPerDay)
})
...

return { ..., selectedDate, dateMatchable, elementsPerDay }

EDIT:

Using computed works:

    const elementsPerDay = computed(() => {
      if (!data.value) {
        return {}
      }

      const elsPerDay = {}
      for (let idx = 0; idx < data.value.length; idx++) {
        const element = data.value[idx]
        const elementDate = formatDate(element.datetime, 'YYYY-MM-DD')

        if (elsPerDay[elementDate] === undefined) {
          elsPerDay[elementDate] = []
        }

        elsPerDay[elementDate].push(element)
      }

      return elsPerDay
    })

I realize that in Options API, you needed to $set() new fields in object for it to be reactive but I thought that reactive() somehow does this for me. Am i wrong?

2 Answers 2

1

Compoisition API plugin is not Vue 3. Actually, what you encounter is a limitation from Vue 2 : https://v2.vuejs.org/v2/guide/reactivity.html#For-Objects.

You need to use $set.

I found an issue about your problem on Github: https://github.com/vuejs/composition-api/issues/334.

Sign up to request clarification or add additional context in comments.

Comments

1

If you're using https://github.com/vuejs/composition-api, you can use $set() by:

import { set } from '@vue/composition-api'
...

setup() {
  set(object, 'key', 'value');
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.