Stencil: Add Fragment to @stencil/core

Created on 16 Oct 2018  路  17Comments  路  Source: ionic-team/stencil

Stencil version:

 @stencil/[email protected]

I'm submitting a:

[ ] bug report
[x] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior:
Rendering multiple elements requires either a wrapping div or returning an array. Returning an array avoids rendering an unwanted <div>, but array format with JSX is hard to read and work with, especially in larger components.

Expected behavior:
Just like React, you could wrap multiple elements in a <Fragment> tag.

Steps to reproduce:
Without fragment:

render() {
  return [
    <div>My first element</div>,
    <div>
        <span>Another element</span>
    </div>,
    <div>And another</div>
  ]
}

Related code:
With fragment:

render() {
  return (
    <Fragment>
      <div>My first element</div>
      <div>
        <span>Another element</span>
      </div>
      <div>And another</div>
    </Fragment>
  )
}

Other information:

This is an extremely simple feature to add, I'm just not sure where it should go in the stencil repository.
The working Fragment code is literally just this one line:

export const Fragment = (props, children) => children

Or without ES6:

export function Fragment(props, children) {
  return children
}

Used as a JSX element, this simply renders the children without rendering an arbitrary wrapping element.

I made a package here to provide this feature, but it would be fantastic if it were available in @stencil/core. People coming from React will love this.

If someone can advise me where in the repo to add this code, I would be happy to make the PR myself.

feature stale issue

Most helpful comment

@manucorporat
I found this super confusing,<Host> is nothing like react <Fragment>,

Error: The <Host> must be the single root component. Make sure:
- You are NOT using hostData() and <Host> in the same component.
- <Host> is used once, and it's the single root component of the render() function.

All 17 comments

But web components need a dash in the tag name, so maybe it should be called ion-fragment 馃

Edit: Uhm sorry I somehow thought this was an issue in the ionic repo 馃檲

@simonhaenisch Yeah, this isn't a web component, it's just a JSX tag! So, no dash.

@michaelauderer we would like to be able to use the short-syntax:

<>

</>

but looks like it's not supported by typescript outside React, "React" is hardcoded into typescript: https://github.com/Microsoft/TypeScript/issues/20469

@manucorporat Yes, this would be even nicer, but until we get support from typescript it would be great to at least include the Fragment element. <Fragment> is still commonly used in React anyways so it would make sense to have this. It could be a long time before Typescript supports the short-syntax.

Is there any update on this? Not having full control over markup is a pretty drastic limitation. Particularly now with CSS grid, markup structure matters for layout and I can't just have unnecessary divs around everything. Pretty sure LitElement doesn't have this drawback.

@o-t-w not sure what you mean because this doesn't limit your ability to have full control over your markup? It's just syntactic sugar (that indeed increases readability a lot), i. e. you can already either use arrays or add the suggested Fragment functional component into your project.

@o-t-w For now, I've already built a solution for it here: https://github.com/michaelauderer/stencil-fragment

If someone can point out where it belongs in the Stencil repository, I'll make a PR. (@manucorporat, any thoughts?)

Stencil 1.0 introduces a new <Host> exported from @stencil/core that can act as a Fragment!

@manucorporat
I found this super confusing,<Host> is nothing like react <Fragment>,

Error: The <Host> must be the single root component. Make sure:
- You are NOT using hostData() and <Host> in the same component.
- <Host> is used once, and it's the single root component of the render() function.

I, too would like to see<Fragment> be part of StencilJS. My use case is that I have a modular web component where consumers of the component can declare plugins, tat themselves render widgets. These renderings are either JSX (Vdom objects) or string values (in case the consumer is a vanilla JS app with no JSX support). When the widget is rendered as string, I need to set the innerHTML property of a containing element. Ideally, without having to use a <div>.

Kudos to @auderer for providing exactly that!

Looks like I celebrated too soon. I misunderstood Fragment to also have an InnerHTML property somehow causing that content to magically be rendered. Instead, it looks like it's just a container that renders child elements. It makes sense that it doesn't do what I expected with InnerHTML.

As @auderer said and did in his Github project, it is just a one-liner:

export default (props, children) => [ ...children ]

Why wouldn't be possible to add it in @stencil/core?

Actually, https://github.com/microsoft/TypeScript/pull/38720 was just merged so we can use the <></> syntax soon!

Ok. Good news. But in the meanwhile, it would be nice to have a Fragment functional component (without the syntactic sugar)

In the meanwhile you could also just add your one-liner into your project(s) 馃槵 Feel free to open a PR though, but no promises that it'll be merged (up to the maintainers). Especially with a better solution in sight already.

No worries. I wasn't going to wait before an action on the codeline would be made. I know how slow an organization is :) On top of that, majority of issues are closed as soon as possible even if the issue exists. We'll see what's happening with the new <>..<> TS syntax support.

Thanks for the issue! This issue is being closed due to inactivity. If this is still an issue with the latest version of Stencil, please create a new issue and ensure the template is fully filled out.

Thank you for using Stencil!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mitchellsimoens picture mitchellsimoens  路  3Comments

MatanYadaev picture MatanYadaev  路  3Comments

guidoknoll picture guidoknoll  路  3Comments

MrMcGibblets picture MrMcGibblets  路  3Comments

lcswillems picture lcswillems  路  3Comments