feathersjs-ecosystem / feathers-vuex

Integration of FeathersJS, Vue, and Nuxt for the artisan developer

Home Page:https://vuex.feathersjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Empty .value when using the setup() method in compositionApi

philipimperato opened this issue · comments

Question about compositionApi and useFind

When querying my Notes service:

const { items, isPending } = useFind({ model: Note, params: { query } })
return { items }

I have a populate items on refresh and on when navigating to the route through the app

Now, when I want to filter the date:

const items2 = items.value.filter(v => v)
return { items, items2 }

items is always populated, but item2 is only populated when I navigate to the component through the app and is empty on refresh. I understand you lose the store... and it appears that the value.filter fires before the data is loaded... so I'm wondering what the point of filtering within the setup method is?

The example shows it doing this: https://vuex.feathersjs.com/composition-api.html#working-with-refs

My only solution is to only return the items RefImpl and filter in a computed property or something, which feels janky and not what the examples encourages.

Any thoughts?


Here is the component. To recap items.length = 1 always, but items2.length will show 0 on refresh of page.

<template lang="pug">
.player-score( v-if="haveLoaded" )
  v-row(justify="center")
    v-col.text-center(
      cols="10"
    )
      .text-h1 {{ items.length }}
    v-col.text-center(
      cols="10"
    )
      .text-h1 {{ items2.length }}
</template>

<script>
import { useFind } from 'feathers-vuex'
import { computed } from '@vue/composition-api'

export default {
  name: 'PlayerScore345',
  setup (props, context) {
    const { Note } = context.root.$FeathersVuex.api
    const noteParams = computed(() => { return { query: { $limit: 1 } } })
    const { items, haveLoaded } = useFind({ model: Note, params: noteParams })
    const items2 = items.value.filter(v => v)
    console.log(items, haveLoaded)
    return { items, items2, haveLoaded }
  }
}
</script>

<style lang="scss" scoped>
</style>
commented

Can you share the whole component please?
It's hard to tell without the rest of the code.

commented

I'd say that filtering on the ref value and returning raw value make it loose reactivity.
You should make it a computed to make it works.

At first sight, it seem's to be a problem with vue 3 reactivity.

@marshallswain It appears that the docs show the filtering on the .value, placing into a variable and returning it within the setup() method. If the reactivity is lost with filter(), wouldn't that mean that the variable is created prior to items being populated?

commented

The variable is always created prior to items being populated, but usually items values are updated after being populated.

The response of the find request has not yet arrived, and as the reactivity has been lost it will no be updated will the requested values.

But once the component is reloaded, the items are there because they are already in the store.

Yup, I figured that, but was thrown off by the usage within the docs
https://vuex.feathersjs.com/composition-api.html#usefind

const { items: todos } = useFind({ model: Todo, params: todosParams })
// Notice the "todos.value"
const completeTodos = todos.value.filter(todo => todo.isComplete)
const incompleteTodos = todos.value.filter(todo => !todo.isComplete)

This makes me think I'm doing it wrong.. when it doesn't appear that I am based on what I'm seeing in practice.

commented

Yep, those two todos arrays should be wrapped in a computed...

ah thanks @philipimperato for pointing out the inconsistency in the docs. And as always, thank you @J3m5 for pitching in to see the fix!

I just pushed up a fix for the docs that wraps those two filtered arrays into computed properties.