Vue warns incorrectly if component is surrounded by functional component
Version
3.0.5
Reproduction link
https://codesandbox.io/s/vue3-slot-invoked-outside-warning-demo-ezuud
Steps to reproduce
Please have a look at the minimal reproduction.
As soon as I create a component inside of a "functional component", it show's a warning.
What is expected?
It shouldn't warn.
What is actually happening?
[Vue warn]: Slot "default" invoked outside of the render function: this will not track dependencies used in the slot. Invoke the slot function inside the render function instead.
The warning is only shown if I create the watch
in MyComponent.vue (or if I access isMandatoryOrSlotVisible.value
directly.)
If I use the same code without the surrounding MyContainer component, it work's without any warning. Since there is no invokation of the slot function in the surrounding MyContainer component, the warning is misleading.
Is this really a bug? I do not think so. As long as you execute the slot functions in setup, you will get this warning, which has nothing to do with whether you use functional components to wrap it.
import { createApp, h, defineComponent } from 'vue'
const Comp = defineComponent({
setup(props, { slots }) {
// a warning raised, this is as expected
const s = slots.default && slots.default()
return () => s
}
})
createApp({
setup() {
return () => h(Comp, () => 'sss')
}
}).mount('#header')
@HcySunYang But then I should get the warning too when I execute the MyComponent directly in App.vue (instead of MyContainer), right? But then there is no warning. so something seems to be wrong there...
A little bit of context of the bigger picture what I try to accomblish: I want to tell the parent component if any of the child components are considered "empty" (based on their data AND slot content). In vue2 those slots where just empty when no element was rendered (with functional components), but since vue3 I can't tell if the component has a v-if="false"
on the root element. I just see the an array with the components or in some cases an entry of type "Symbol(Comment)" ($el
is not accessible).
So I guess I have to use provide
and inject
. But those need to be performed in setup
(and not in render
). So there seems to be no other way to invoke the slot function in setup, to determine if there is something to show.
Ok, I made a PR to make the warning consistent when calling the slot function outside the render function.
However, more and more users request similar capabilities. They hope to call the slot function in the setup
function to determine whether the slot content exists or meets expectations. Maybe we don’t need to report that warning message, but instead, emphasize it in the document.