Child component <slot v-if="false"> will still evaluate parent slot code
See original GitHub issueVersion
2.5.16
Reproduction link
https://github.com/bbugh/v-if-slot-issue/commit/ffd6d476bf378936566b4916c1342af4310ef412
Steps to reproduce
-
Create a child component with a conditional slot:
<template> <div> <slot v-if="showSlot" /> </div> </template>
-
Use the slot in a parent component, using code that should not be called when
v-if
resolves asfalse
:<conditional-slot :showSlot="false"> {{ example.should.not.be.called }} </conditional-slot> data: () => ({ example: {} })
Observe that slot code is called, and fails because “example” is an empty object.
A runnable demo of this is in the linked repository.
What is expected?
The behavior is expected to match v-if
’s behavior in other circumstances, which is that the code in the if
block is not evaluated when the conditional check resolves as false.
What is actually happening?
The parent slot code is always evaluated, regardless of the value of v-if
in the child component.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:9
- Comments:10 (3 by maintainers)
Top Results From Across the Web
VueJS slots: Why child method passed in via slot from parent ...
In this demo, I pass in a method to a child component (defined in child) via slots from parent. However that method does...
Read more >Vue Tricks - Passing Slots to Child Components - Dev Induct
In the end, the focus is going to be on passing all slots from the parent component to the child. This article assumes...
Read more >Parent & Child Components - Halogen Guide
This slot is a place where the component can produce Halogen HTML until it ... the child component, which lets the parent component...
Read more >Can't access data property from parent in slot child component
I have two components rad-list and rad-card, I placed a slot element in rad-list where I will place rad-card, now rad-card receices an...
Read more >Slots - Vue.js
parent component passing slot content FancyButton('Click me! ... Slot content does not have access to the child component's data.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
You can use the new
v-slot
syntax (<template #default></template>
) to prevent the slot content from rendering until its needed.v-slot
documentationI’d just like to elaborate on @yyx990803 and @sirlancelot’s answers with a bit more detail for people landing on this page looking for quick answers. Take the following code as an example (preview at https://jsfiddle.net/yd2Lpcf1/4/):
When this is run in the fiddle linked above then the preview will be blank for a second, then “Hello John” will be shown twice. If run in its own page, then the error console will show the error
Cannot read property 'name' of null
, referring to the fact thatperson.name
defined in the<layout>
section was eagerly evaluated and raised an error. This error is thrown every second. This demonstrates that slots are evaluated eagerly and that the error halts the rendering of the child component and the parent component - “Loading” isn’t printed in the firstv-if
, nor in the one in the child component. It also demonstrates that, even though the slot was eagerly evaluated originally, it is still re-rendered when the value ofperson
changes.Following @sirlancelot’s recommendation, the only thing that needs to change is to nest an extra
<template>
layer inside the<layout>
:When the page is re-run then the preview will show “Loading” twice, for a second, and then “Hello John” will be shown twice, and these values will change every second. The error console will be blank. This demonstrates that the slot is lazily evaluated following the expected
v-if
logic, as expected, and the whole component is properly re-evaluated reactively, instead of just being re-rendered.In short, when you’re using a component with a conditional slot like
<MyBaseComponent>...</MyBaseComponent>
, simply wrap the content as @sirlancelot described (<MyBaseComponent><template #default>...</template></MyBaseComponent>
), and the default slot will evaluate in the way you’d expect.As an aside, if support for Vue 2.0 is expected to continue for much longer, I would recommend updating the documentation for slots with a section on the “Eager Evaluation” caveat and how it can be solved using the
v-slot
workaround.