Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add loaded prop to subscription state #1314

Closed
Soviut opened this issue Feb 26, 2023 · 5 comments
Closed

Add loaded prop to subscription state #1314

Soviut opened this issue Feb 26, 2023 · 5 comments
Labels

Comments

@Soviut
Copy link
Contributor

Soviut commented Feb 26, 2023

What problem is this solving

On my index page, I have a "no items" message that is supposed to be displayed if there are no items in the collection.

The following naïve approach will briefly flash the message even if there are items in the collection because useCollection starts with an empty array before populating it.

<script setup lang="ts">
const items = useCollection(collection(db, 'items'))
</script>

<template>
  <p v-if="items.length === 0">No items yet</p>
</template>

I then found the subscription state in the docs, which has a pending reactive value. However, the following still flashes the message since pending seems to change before the collection has fully loaded.

<script setup lang="ts">
const { data: items, pending }= useCollection(collection(db, 'items'))
</script>

<template>
  <p v-if="!pending && items.length === 0">No items yet</p>
</template>

So I finally wound up using the promise from the subscription state. While this worked, it was very awkward to integrate reactively.

<script setup lang="ts">
const { data: items, promise } = useCollection(collection(db, 'items'))

const loaded = ref(false)
promise.value.then(() => {
  loaded.value = true
})
</script>

<template>
  <p v-if="loaded && items.length === 0">No items yet</p>
</template>

Proposed solution

I propose introducing a dedicated loaded prop to the subscription state. It would be a reactive boolean that only toggles true when the data is initially loaded. This is similar to the VueApollo loading state except there it's a loading prop that toggles each time new data is loaded.

My current workaround looks like

type LoadableCollection = ReturnType<typeof useCollection> & {
  loaded: Ref<boolean>
}

export const useCol = (...args: Parameters<typeof useCollection>) => {
  const loaded = ref(false)

  const res = useCollection(...args) as LoadableCollection

  res.promise.value.then(() => {
    loaded.value = true
  })

  res.loaded = loaded

  return res
}

And I use useCol() wherever I'd normally use useCollection().

Describe alternatives you've considered

Another option would be to make pending stay true until the data had fully loaded. While this technically alters existing API behaviour, it's unclear how pending is even supposed to be used if it doesn't work like I originally expected it to. Is that a bug?

@posva
Copy link
Member

posva commented Feb 26, 2023

Mmh, normally pending serves that purpose. For arrays you might need the wait prop set to true

@Soviut
Copy link
Contributor Author

Soviut commented Feb 26, 2023

I'm willing to investigate and try and make a PR for this. Would ensuring the pending always toggles after the promise resolves be considered breaking the API?

@posva posva closed this as completed in 3186afb Feb 26, 2023
Copy link
Member

posva commented Feb 26, 2023

pending wasn't set as it should. It should now be fixed

@posva posva added bug and removed feature request labels Feb 26, 2023 — with Volta.net
@Soviut
Copy link
Contributor Author

Soviut commented Feb 26, 2023

Awesome! I might try to help write some additional documentation around the subscription state to explain the use cases for using pending to display a loading message versus waiting for it to resolve to display an empty collection message.

@Soviut
Copy link
Contributor Author

Soviut commented Feb 26, 2023

I just tried the update (release @3.1.0) and it works as expected now.

<p v-if="!pending && items.length === 0">No items yet</p>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants