App can't rerender when use `v-if` in slots
Version
3.0.5
Reproduction link
https://stackblitz.com/edit/vue-t57npn?file=src/App.vue
Steps to reproduce
- click the img, the app will set the state show to true
- the child component won't rerender
What is expected?
I hope the child component could rerender
What is actually happening?
onUpdate function won't run.
First of all, you should not directly manipulate the slot's VNode, your code is fragile, and I don't see any meaningful intentions of your code.
The reason for this issue is that the ref(show
) in the slot only collects the rendering function of the child component as a dependency, but in the sub-components, because you use v-if
, the slot will not be rendered, which causes the ref(show
) to not collect any components as dependencies, so modifying its value is useless.
Try the modified version: https://codesandbox.io/s/nostalgic-dew-ms9s9?file=/src/App.vue
My intention is to have a container wrap the slot. When slot does not exist, this container does not exist either. However, the demo you gave cannot achieve the function I want. I don't want to give this control to the outside.😢
First of all, you should not directly manipulate the slot's VNode, your code is fragile, and I don't see any meaningful intentions of your code.
The reason for this issue is that the ref(
show
) in the slot only collects the rendering function of the child component as a dependency, but in the sub-components, because you usev-if
, the slot will not be rendered, which causes the ref(show
) to not collect any components as dependencies, so modifying its value is useless.Try the modified version: https://codesandbox.io/s/nostalgic-dew-ms9s9?file=/src/App.vue
Use a computed() property.
export default {
name: "HelloWorld",
setup(props, { slots }) {
const withText = computed(() => {
const text = getFirstValidNode(slots.default?.({ withText: true }));
return !!(text && isValidElementNode(text));
});
return { withText };
},
};
https://codesandbox.io/s/trusting-leftpad-b2pfs?file=/src/components/HelloWorld.vue
Use a computed() property.
export default { name: "HelloWorld", setup(props, { slots }) { const withText = computed(() => { const text = getFirstValidNode(slots.default?.({ withText: true })); return !!(text && isValidElementNode(text)); }); return { withText }; }, };
https://codesandbox.io/s/trusting-leftpad-b2pfs?file=/src/components/HelloWorld.vue
tks, it work.
but I still have a question, why computed
can collect dependencies of slots
. as far as I know slots
are not reactive.
did I not understand the docs? https://v3.vuejs.org/guide/composition-api-setup.html#context