Vue-next: App can't rerender when use `v-if` in slots

Created on 4 Jan 2021  路  4Comments  路  Source: vuejs/vue-next

Version

3.0.5

Reproduction link

https://stackblitz.com/edit/vue-t57npn?file=src/App.vue

Steps to reproduce

  1. click the img, the app will set the state show to true
  2. 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.

Most helpful comment

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

All 4 comments

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 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

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

Was this page helpful?
0 / 5 - 0 ratings