Subscribe on changes!

`unwrapInjectedRef` has no effect in `<script setup>`

avatar
Dec 16th 2022

Vue version

3.2.45

Link to minimal reproduction

https://codesandbox.io/s/boring-goldwasser-75kbqb?file=/src/components/Btn.vue:112-153

Steps to reproduce

Toggle the radio buttons at the top, which controls the size props.

For the button groups, it is only passed to BtnGroup, not the individual Btn instances. The group then provides it as a ref, and Btn.vue injects it as the size prop's default value.

What is expected?

Since app.config.unwrapInjectedRef is true, I was hoping the injected ref would be unwrapped in the button's props object. In which case the first button group's size would match the others as you toggle the radio buttons.

What is actually happening?

The injected ref remains a ref. The buttons in the first button group do not change size, since the height computed looks for props.size, not props.size.value.

System Info

No response

Any additional comments?

We have a UI library where lots of components support he same size values – buttons, inputs, etc. I wanted to provide/inject those so that they can inherit them from the nearest ancestor that has an explicit value. Not just for button groups, but even entire forms or applications.

Someone tipped me off to unwrapInjectedRef on Discord, but I couldn't get it to do anything. As far as I can tell, it only works for the Options API, here:

https://github.com/vuejs/core/blob/4c3203b9b7b362fe61150ad05e231e2a35e11356/packages/runtime-core/src/componentOptions.ts#L666

Maybe I have misunderstood and this isn't what unwrapInjectedRef is for, or there's a reason it can't be done with the composition API?

My solution for now was to lift the same technique into my own util, as used by BtnWithFix.vue in the reproduction. Mutating the props object feels iffy though, so I don't know if that's a robust way to do it:

https://codesandbox.io/s/boring-goldwasser-75kbqb?file=/src/manuallyUnwrapRefs.js

avatar
Dec 17th 2022

That setting only matters to injections in Options API, so you don't have to type this.someInjection value. As there is no this in composition API, unwrapping the injection itself doesn't make sense.

And yes, props is not unwrapped, that's by design. Unwrapping usually happens in the parent template, leaving the door open to send an untapped value if an edge case may call for it.

avatar
Dec 18th 2022

Thanks, appreciate the clarification @LinusBorg 👍

Bit of a bummer since it would have been a really elegant way for components to provide default prop values for their descendants, but nothing I can't work around.