Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functional component not rendering named slot (following #8871) #8878

Open
nicolas-t opened this issue Oct 1, 2018 · 7 comments
Open

Functional component not rendering named slot (following #8871) #8878

nicolas-t opened this issue Oct 1, 2018 · 7 comments

Comments

@nicolas-t
Copy link

nicolas-t commented Oct 1, 2018

Version

2.5.17

Reproduction link

https://codesandbox.io/s/p9mx85qpz0

Steps to reproduce

nothing in particular.

What is expected?

It should display Hello World

What is actually happening?

It displays Hello


Following #8871 I made App.vue non-functional:

If you make Child.vue non-functional it works: https://codesandbox.io/s/pw5lzx2w90

If you use default (not named) slots it works: https://codesandbox.io/s/04jrp3y4ln

@murr4y
Copy link

murr4y commented Oct 1, 2018

Responded on the Vue Forum as well, is this maybe the same issue as in #7587?

It works by using a scoped slot:
https://codesandbox.io/s/0p96w8o1pw

@joedski
Copy link

joedski commented Nov 19, 2018

I've been running into this for a little while now, trying to make a simple functional component to use with values created by daggy.js.

I've created a codesandbox thingy with a number of cases showing the effects of this.

Peeking at the VNodes being created during the render call, the issue seems to be caused by the root element of a named unscoped slot passed to a functional component still having data.slot on its VNode when that VNode is returned by the functional component.

Example results of using a named, unscoped slot with a plain DOM node:

Render Template:
  transition[name=overlay-fade]
    my-functional-component
      div.busy-overlay[slot=waiting]
        spinner

VNode: transition[name=overlay-fade]
  tag: 'vue-component-19-transition'
  children: undefined
  componentOptions:
    tag: 'transition'
    children: [
      VNode: div.busy-overlay[slot=waiting]
        tag: 'div'
        data:
          slot: 'waiting'
        children: [
          VNode: spinner
            tag: 'vue-component-25-spinner'
            children: undefined
            componentOptions:
              tag: 'spinner'
        ]
    ]

Compare this to the use of a template tag as the slot root:

Render Template:
  transition[name=overlay-fade]
    my-functional-component
      template[slot=waiting]
        div.busy-overlay
          spinner

VNode: transition[name=overlay-fade]
  tag: 'vue-component-19-transition'
  children: undefined
  componentOptions:
    tag: 'transition'
    children: [
      VNode: div.busy-overlay
        tag: 'div'
        data:
          slot: (not present)
        children: [
          VNode: spinner
            tag: 'vue-component-25-spinner'
            children: undefined
            componentOptions:
              tag: 'spinner'
        ]
    ]

The exact component used to wrap the functional component doesn't matter, as demonstrated in the codesandbox example at the top of this post, I just ran into this using the Transition component most recently, hence the appearance of transition in the outlines above.

For now, I'm going to stick to wrapping the contents of slots in <template>s. I may also add a wrapper function for getting normalized slot contents in functional components.

@why06
Copy link

why06 commented Mar 5, 2019

I've ran into this issue too. Seems to only occur when a functional component wraps another functional component.

@MrJmpl3
Copy link

MrJmpl3 commented Jun 17, 2019

I have same problem, When a functional component wraps another functional component.

@moonRider
Copy link

moonRider commented Jul 2, 2019

there should be an anwser you want here
#7587

@MrJmpl3
Copy link

MrJmpl3 commented Jul 2, 2019

there should be an anwser you want here
#7587

Ok, can be a solution , but I use SFC functional with default slot:

<template functional>
</template>

@posva
Copy link
Member

posva commented Jul 2, 2019

In this specific scenario, the Parent component should be written like this:

  render(h, context) {
    context.data.scopedSlots = {
      username: () => h('span', {}, 'World')
    }
    return h(Child, context.data, [])
  },

I think we may need to adapt the functional component to allow passing a child with a slot attribute:

  render(h, context) {
    context.data.scopedSlots = {
      username: () => h('span', {}, 'World')
    }
    return h(Child, context.data, [
      h('span', { slot: 'username' }, 'World')
    ])
  },

@nickmessing I imagine the jsx plugin transforms into this because it has no way of knowing if Child is functional or not

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants