1
votes

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?

1

1 Answers

0
votes

Compoisition API plugin is not Vue 3. Actually, what you encounter is a limitation from Vue 2 : https://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.