vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.65k stars 8.33k forks source link

Make reactive props destructurable #8715

Closed mrniamster closed 1 year ago

mrniamster commented 1 year ago

Vue version

3.3.4

Link to minimal reproduction

https://stackblitz.com/edit/vue-e8tje3?file=package.json,src%2FApp.vue

Steps to reproduce

https://github.com/TanStack/query/issues/5658

What is expected?

Vue should unwrap refs that are passed to the template, but it seems that they are doing it only for direct accessed properly and dot notation access

What is actually happening?

All properties returned by vue-query are ref's. Otherwise if you try to destructure them, you will loose reactivity, This seems to be a problem with v-if implementation, cause it works properly with regular value interpolation.

System Info

No response

Any additional comments?

This seems to be a problem with v-if implementation, cause it works properly with regular value interpolation.

See https://stackblitz.com/edit/vue-e8tje3?file=src%2Fmain.js,src%2FApp.vue

I had to use unref in the template to make it work. Seems to be a Vue bug.

All properties returned by vue-query are ref's. Otherwise if you try to destructure them, you will loose reactivity, which is a very common problem among new Vue devs. Vue should unwrap refs that are passed to the template, but it seems that they are doing it only for direct accessed properly and dot notation access - query.isLoading is not unwrapped.

This is not strictly a problem with vue-query. You could potentially open a feature-request in Vue repository to get it working.

We could potentially just return reactive object and count on users to properly handle destructuring with toRefs conversion, but i doubt that will be a good idea (more confused users than benefits). There is an RFC in place to make reactive props destructurable, but until that lands and will be supported in custom composables, i doubt we could do anything about it.

LinusBorg commented 1 year ago

I think you're talking about this documented caveat:

https://vuejs.org/guide/essentials/reactivity-fundamentals.html#caveat-when-unwrapping-in-templates

According to this docuemented behaviour, what you need to do is this use .value like in other places, too:

<span  v-if="query.isLoading.value">

this is kinda so that you till have a way left to actually handle a ref a a ref (without unwrapping it) in the template.

when "printing" a ref in an interpolation ({{ query.isLoading }}) we do unwrap it as that's the only option that makes sense.

It's not ideal, overall, but that's the way it works and changing this would be a breaking change, so we would need to postpone it till we start talking next major release in the future. It's already on our list of things to look at for that.