React: Add fragment API to allow returning multiple components from render

Created on 2 Sep 2014  ·  148Comments  ·  Source: facebook/react


Note from maintainers:

We know this is an issue and we know exactly what set of problem can be solved. We want this too but it is a _hard problem_ with our current architecture. Additional comments expressing desire for this feature are not helpful. Feel free to subscribe to the issue (there's button in the right hand column) but do not comment unless you are adding value to the discussion. "Me too" and "+1" are not valuable, nor are use cases that have already been written in the comments (e.g., we know that you can't put <tr> or <dd> elements with a <div>).


Consider the following:

var ManagePost = React.createClass({

  render: function() {
    var posts = this.props.posts

    var something;
    var somethingelse;

    var row = posts.map(function(post){
      return(
        <div>
          <div className="col-md-8">
          </div>
          <div className="cold-md-4">
          </div>
        </div>
      )
    });

    return (
        {row}
    );
  }

});

If you remove the <div></div> in the map, you get the following error: _Adjacent XJS elements must be wrapped in an enclosing tag_

it isn't till I re-add the surrounding, and rather pointless, divs that it compiles with out issue. I am running 0.11.1

Is this being addressed? It adds extra, and again - IMO - useless and pointless html to the page, that while harming nothing - looks messy and unprofessional. Maybe I am just doing something wrong, please enlighten me if I am.

Most helpful comment

I think we can close this.

Returning arrays from components is supported since React 16 Beta 1 which you can try now.

There are still some limitations (SSR support is not ready) but we’re tracking them in #8854 and will fix before the final 16 release.

Thanks to everyone for your feedback!

All 148 comments

Because when you don't put the wrapper, it desugars to this:

return React.DOM.div(...)React.DOM.div(...)

Which doesn't make syntactical sense. The jsx compiler page might help if you need a visual mapping.

That being said, it's possible to desugar this to [div, div] instead. This is hard, somewhat controversial and won't be implemented in a near future.

(I don't think it's particularly controversial but it does add code complexity and hasn't been done yet.)

IIRC @syranide has a few comments on this

@chenglou Hehe.

I had a brief chat about it with chenglou a little while ago, I don't really lean one way or the other at the moment. I see a lot of hidden dangers in allowing a composite components to return multiple components and it breaks a lot of intuitive assumptions, but I don't know of any (right now) good practice use-cases that would obviously benefit from this.

The simplicity of returning at most one component means that it's very easy to reason about what you see, if not, <table><TableHeader /></table> could actually render any number of rows, you have no way of knowing other than inspecting TableHeader and whatever composite components it returns.

I feel like being able to return multiple components only moves the responsibility of wrapping components as necessary from the "composite component" to whatever "renders the composite component". The component "that renders composite component" rarely has or should have the knowledge of whether to wrap composite components or not, whereas children are more likely to have knowledge of their parents.

But perhaps it's simply a case of developer responsibility. There may be good use-cases for both and we should just look past the inevitable misuse.

@sebmarkbage Probably has a few comments too :)

We will probably never allow that syntax implicitly. You would need a wrapper like

<>
  <div className="col-md-8">
  </div>
  <div className="cold-md-4">
  </div>
</>

OR

[
  <div className="col-md-8">
  </div>,
  <div className="cold-md-4">
  </div>
]

However, even this doesn't work. Often, it's probably for the best. It can be confusing for consuming components when a child might expand into multiple elements.

But, really, the only reason we don't support this right now is because it's hard to implement. Hopefully, we'll be able to support it sometime in the future but probably not short term. Sorry. :/

can this not affect things like jquery or other libraries that target specific elements, so if you do something like $('#id-name').children(), the following:

<div id="id-name">
  <div>
    <div class="class-name">
    </div>
  </div>
</div>

the <div> and <div class="class-name"> would be selected in this case. (If I understand this properly)

It affects also css selectors in the very same way @AdamKyle posted before.

Any updates on this issue?

Spent a couple of minutes understanding why my component didn’t work. I feel like there should be a notice somewhere, maybe I missed it ? Maybe it is obviously wrong to try :

var Optimistic = React.createClass({
  render: function() {
    return ( 
      <h1>{this.props.name} loves React</h1>
      <p>React doesn’t. Idea: sprinkle some divs here and there.</p>
    );
  }
});

React.render(
  <Optimistic name="Peter" />,
  document.getElementById('myContainer')
);

@gabssnake You should have gotten a JSX compile error with the error "Adjacent XJS elements must be wrapped in an enclosing tag"; did you not see the error or was it not clear in its explanation?

Thank you for your answer @spicyj. Well, I meant a notice in the React documentation. Yes, the console did show an error, but the need to wrap didn’t make sense to me at first. That is why I searched and got here.

I've had this pain as well... particularly painful for my designer, as a matter of fact. It'd be kind of nice if a component could output a node (therefore node-list or fragment) instead of an element.

Just saying.. I'm not advocating returning multiple children from component _but_ I'd love to do that in render* methods that I extract from render:

  render: function () {
    return (
      <div className={this.getClassName()}
           style={{
             color: this.props.color,
             backgroundColor: this.props.backgroundColor
           }}>
        {condition ?
          this.renderSomething() :
          this.renderOtherThing()
        }
      </div>
    );
  },

  renderSomething() {
    return (
      <>
        <div className='AboutSection-header'>
          <h1>{this.props.title}</h1>
          {this.props.subtitle &&
            <h4>{this.props.subtitle}</h4>
          }
        </div>,

        {hasChildren &&
          <div className='AboutSection-extra'>
            {this.props.children}
          </div>
        }
      </>
    );
  }

But I should probably just shut up and use keys.

@gaearon You can do that already though, you just need to return an array for now (which is a bit cumbersome though yes) ... buuuuut, you can work around that, I have hacked my own <Frag> component which is translated to an array (overloaded React.render) ... you could also do return <NoopComp>...</NoopComp>.props.children I assume, if you want to avoid hacks.

EDIT: My bad, I overloaded React.createElement not React.render.

The problem with arrays is they trip our designer. Need commas, explicit keys.

@gaearon Yeah you can avoid the commas using either of my two workarounds for now (if you find either acceptable)... but what you do mean with explicit keys?

If I use array syntax, I need to specify key on each element. Not that it's hard to do, but feels awkward because I know they never change.

@gaearon Ah yes, I choose to just mentally ignore that warning for now :), if you really want to to avoid it, you can do <MyComp children={this.renderWhatever()} /> to avoid it (EDIT: although you obviously can't use that if you have adjacent children, you could use some flattening helper... but yeah).

Another case I've ran into with a UI kit. When you are placing children inside a fixed scrollable container like so:

return (
  <div style={{
    position: fixed
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    overflow-y: scroll;
  }}>
    {this.props.children}
  </div>
);

The children now must be passed as an array, but if a composite class is passed, it must also implement those styles to avoid breaking it. Just adds a layer of complexity. But I can completely understand how complex it must be to make the change. Just throwing my hat in for support.

I have another use-case I described in detail over here #3415. But I can workaround it for now and understand that it is hard to implement and rare.

I know nothing about react internals (yet), but I'll just throw in an idea how you could mark such virtual parent elements/fragments in the DOM: comments. E.g.

<A>
    <B></B>
    <Fragment>
        <C></C>
        <D></D>
    </Fragment>
    <E></E>
</A>

would render to

<a>
    <b></b>
    <!--<fragment data-reactid="">-->
        <c></c>
        <d></d>
    <!--</fragment>-->
    <e></e>
</a>

This means c and d will be treated as children of sth. (including the nested reactid to not conflict with b and e). I've seen other frameworks "misuse" comments for these kind of semantical jobs.

@Prinzhorn I think you might be confusing DOM output with React's JSX.

In case it's useful: @Prinzhorn's suggestion of using HTML comments to map "fragment components" to the DOM is the same approach that Knockout uses. Knockout calls these "virtual elements".

<!-- ko component: "message-editor" -->
<!-- /ko -->

(from knockout docs)

Also, another use case for this - the extra wrapping elements can be problematic when using flexbox.

@aldendaniels absolutely agree, I've ran into flexbox issues already.

I ran into this with flexbox with dependent dropdowns. Where A would render and manage the first dropdown, followed by B or C or D depending on the value of A's dropdown, which would each render the appropriate number of dropdowns, e.g.

<A>
 <Drop />
 <C><Drop /><Drop /></C>
</A>

A, B, C, and D are stateless so I changed them from class B {render(){ this.props }} to function B(props){ return [...]; }.

In this case, it doesn't much matter to the parent that multiple children are rendered, it's just to deal with my CSS. There are things I'd do differently if these didn't need to be reused (another component needs B, C, and D).


As an alternative, maybe a way to unravel it from the parent? I don't have any specific ideas of how that'd look.

I hit a scenario today that I think is a good use case for this feature: A component that renders multiple <script> elements, where it could be rendering into the <head> element of the page. Any wrapper element there would be bad.

My scenario is wanting to have a component that is responsible for rendering the <script> tag both for the runtime code needed on the page as well as another <script> tag that carries the localized strings to be used by the runtime code. For example:

<html>
    <head>
        <script language="runtime.resources.en-us.js"></script>
        <script language="runtime.js"></script>
    </head>
    <body>
    ...
    </body>
</html>

In this case, I'd like to have the code authored as:

var RuntimeScripts = require('./Runtime')
...
return (
    <html>
        <head>
            <RuntimeScripts language="en-us" />
        </head>
    </html>
)
...

I also ran into some flexbox issues. Nothing that can't be solved in CSS, but one of the "beauties" of flexbox is that you need less "wrapper" elements everywhere to make your layout work, but you'll still end up with wrapper elements everywhere when using React since you always wrap whatever you return in div/div or similar, unless it makes sense to have a container.

For all the use-cases presented here I'm pretty sure you could replace <BunchOfComponents /> with {getBunchOfComponents()} and the visual output would be the same, without introducing the practical and technical issues related to having components with fragments as root.

@syranide but every time one of the components changes all of its siblings need recalculating...

Also if you use plain coffeescript it's easy to return an array, so please decouple the functionality from the jsx representation.
IOW if it's easy to handle a returned array of elements, don't wait for jsx to catch up.

@syranide but every time one of the components changes all of its siblings need recalculating...

@wmertens Yes, but many times you would have that anyway because the parent would need to rerender for other reasons, or simply because you receive the data through props anyway. But yes, that is the difference, but it doesn't mean this approach is right, it's an optimization and there are many ways to accomplish them.

Also if you use plain coffeescript it's easy to return an array, so please decouple the functionality from the jsx representation.

That is irrelevant and this is not a problem with JSX. A big issue is that you lose the technical, practical and intuitive assumption of one component = one element/node. I can't speak for the devs but I would not give up that willingly, it's a very useful assumption to have. I'm sure there are equally good or better optimizations that could be designed if optimization is the only the reason people want this.

@syranide the biggest problem is that you can't always use a wrapping
element in html, like in tables, lists, flexbox, head... Working around
that leads to ugly code.

I would be perfectly happy with a virtual wrapper element that only renders
comments, as suggested before.

On Fri, May 29, 2015, 3:56 PM Andreas Svensson [email protected]
wrote:

@syranide https://github.com/syranide but every time one of the
components changes all of its siblings need recalculating...

@wmertens https://github.com/wmertens Yes, but many times you would
have that anyway because the parent would need to rerender for other
reasons, or simply because you receive the data through props anyway. But
yes, that is the difference, but it doesn't mean this approach is right,
it's an optimization and there are many ways to accomplish them.

Also if you use plain coffeescript it's easy to return an array, so please
decouple the functionality from the jsx representation.

That is irrelevant and this is not a problem with JSX. A big issue is that
you lose the technical, practical and intuitive assumption of _one
component = one element/node_. I can't speak for the devs but I would not
give up that willingly, it's a very useful assumption to have. I'm sure
there are equally good or better optimizations that could be design if
optimization is the only the reason people want this.


Reply to this email directly or view it on GitHub
https://github.com/facebook/react/issues/2127#issuecomment-106810565.

fwiw, It's relatively easy to hack a "fragment" component into React that is treated as an array of its children by React. It will auto-generate keys, but since it happens after the initial validation of components, it won't throw the usual "no keys supplied" error.

With that said, that hack only solves what @gaearon was talking about above - not having to deal with ugly array syntax/setting arbitrary keys in your JSX - and not the issue of returning multiple nodes at the root of a component's render method.

I have a problem with the idea that a component needs to return one "element/node". To me, it seems perfectly reasonable for a JSX structure of:

<Main>
  <Foo />
  <Fragment>
    <Bar />
    <Baz />
  </Fragment>
</Main>

to end up as the DOM:

<div>
  <div>Foo</div>
  <div>Bar</div>
  <div>Baz</div>
</div>

I don't think this is a principle-of-least-surprise violation because components already do all kinds of "surprising things" with the DOM using lifecycle hooks (just look at the common wormhole pattern). It is generally accepted that a component will not necessarily result in a single element being created, and that's fine, because some compromises have to be made to work with the DOM.

This isn't about "optimizations," either, or even just about not liking array syntax. As many users have mentioned, _wrapper elements break styling and layout in serious ways_. Tables are the most obvious, but Flexbox is also a major issue. I already have CSS that just reapplies flex rules to wrapper elements that only exist because of React, and it's pretty ugly.

For all the use-cases presented here I'm pretty sure you could replace with {getBunchOfComponents()} and the visual output would be the same, without introducing the practical and technical issues related to having components with fragments as root.

This requires developers to compromise on making isolated, reusable components - heaven help them if they decide they want to reuse their bunch of components elsewhere - because of an underlying implementation issue in React. I don't think that should be accepted.

@thomasboyt

EDIT: My mistake, I conflated some of your arguments with the table-discussion above, I largely agree with what you're saying I think. But there are still problems with components being opaque, so what's intended as a useful transparent wrapper becomes opaque to the parent. Imagine <Wrapper1><Wrapper2>...</Wrapper2></Wrapper1>, Wrapper1 cannot see the children of Wrapper2. So perhaps wrapMyElements(...) simply is a better solution all-around still (including any other necessary supporting functionality).

I have a problem with the idea that a component needs to return one "element/node". To me, it seems perfectly reasonable for a JSX structure of:

Components are more than just dumb wrappers, they have a purpose. IMHO it seems that returning multiple elements blocks some very useful expectations. For example, React.render will get a companion in the future which renders an element and returns the nodes, this must now produce an array of nodes instead.

But I think a very important issue is that of readability which IMHO is the biggest selling point of React, everything is explicit.

<table>
  <tr>
    <td />
    <td />
    <td />
  </tr>
  <tr>
    <Columns1 />
    <Columns2 />
  </tr>
</table>

Looking at that it makes no sense, where is the 3rd cell coming from? Perhaps it's actually wrong and it's rendering 2 or 4 cells, who knows, perhaps it's actually dynamic and depends on a prop or external state? There are many of variations of this problem which only get harier when you consider other non-HTMLDOM frontends which may have explicit expectations. Another thing to consider is that elements are opaque, so if you replace <tr /> with <MyMagicalTr /> then it is not able to interact with the individual cells or even deduce how many there are, so even though <MyMagicalTr /> may only accepts <MyMagicalTd />'s there is no guarantee it can actually interact with them.

This requires developers to compromise on making isolated, reusable components - heaven help them if they decide they want to reuse their bunch of components elsewhere - because of an underlying implementation issue in React. I don't think that should be accepted.

"This requires developers to compromise on making isolated...", but that is exactly the problem if you ask me, if a component can return multiple elements it's no longer isolated, it's substituted, the component is leaking into the parent.

Hammer, nails. It being an underlying implementation issue is a separate issue from whether or not this should actually be done at all. It's not my decision, but I don't see how one rare use-case is convincing argument without considering the trade-offs that comes with it or what other alternative solutions there are.

IMHO I don't see the problem with {getBunchOfComponents()}, it's explicit, it allows us to keep our useful expectations. If performance is a problem then React.createSmartFragment() (or w/e) to the rescue, a transparent array/object-like type but one which can update independently from its parent.

Again, the React devs are the authority (not me), but I don't see a convincing argument here considering the various side-effects. I'm not even sure I agree with the presented solution being a good pattern at all, even if it was supported.

EDIT: To clarify, perhaps components may be able to return multiple elements in the future because there are other obviously beneficial use-cases, especially in the context of passing through children (like the one you show @thomasboyt), readability is maintained.

I think I'll need a bit more coffee before I can respond to the philosophical side of this conversation (thanks for the very good points, @syranide), but on the implementation side, I started poking around at this last night to see how viable a change of this scope is, leading to this spike: https://github.com/facebook/react/compare/master...thomasboyt:fragment

And threw up a little demo here: http://www.thomasboyt.com/react-fragment-demo/

Some observations on the implementation side of things:

  • Not surprisingly, it's very tricky to retrofit a system that expects "1 component = 1 node" to support more nodes ;)
  • I initially thought to try tracking fragments on the DOM operations side, so that ReactMultiChild's generated mutation instructions could stay the same and treat fragments like any other node. I couldn't think of a good way to add state about node counts/which nodes are fragments into the DOM state tracking, though. Something like the comment fencing @Prinzhorn noted could work, but I'm wary of anything that would require a DOM lookup, considering the relative cost.
  • With that idea discarded, I added a _nodeCount field to all children of a ReactMultiChild component, so that it could track the number of root nodes a fragment actually contains.

Problem is, while this is easy enough to do on an initial render by just counting the children of a fragment, updating the fragment's node count on subsequent mutations seems trickier. This is still not done on my branch (see https://github.com/thomasboyt/react/issues/2).

  • Many DOM operations rely on accessing the parent node of an element, looked up by the internal node ID, to append/move/remove elements (see https://github.com/thomasboyt/react/issues/3). Since the ReactMultiChild's updateComponent cycle is responsible for passing this ID along, it could be changed to do a lookup of the closest parent that has a DOM node, but that sounds expensive. Alternatively, it may be possible to have an internal registry of fragment keys to their "real node" keys.

I'm still not convinced that requiring fragments to maintain a count of their root nodes is the best way to do this (though it did at least get me to that demo), and this was all hacked together quite rapidly and quite late at night, so if anyone else has a suggestion for implementation, feel free to chime in :>

@thomasboyt IIRC the main implementation obstacle comes from React referencing child nodes by mountIndex, this does not work when one "node" can suddenly become any number of nodes and this may happen without invoking the parent and it may also happen several components deep (wrapping). If I'm not mistaken it's pretty trivial to have React support multiple root elements as long as the number never changes.

So I don't think it would be especially hard to just make it work in React, but a truly proper solution is more problematic and should probably involve dropping mountIndex.

@syranide Right; the solution I'm working on actually introduces a new nodeIndex that is supposed to be the "real offset" of a node (which reminds me that I need to go back and remove mountIndex, since I think it's now unused in my branch).

But, as you note, this is problematic if the number of root elements changes, as the nodeIndex of a component needs to be updated whenever a previous sibling component's node count changes. Still need to find a solution for that.

I've also run into flexbox issues. @syranide could you please elaborate a bit more on your "getBunchOfComponents" proposed solution? Being new to React it's hard to fully get the idea where to define this function / how to apply it.

@landabaso

function getBunchOfComponents(...) {
  return [<ColumnA key="a" />, <ColumnB key="b" />];
}

Hey,

I've not read the whole thread but here's a render optimization usecase that may require this feature:

http://stackoverflow.com/questions/30976722/react-performance-rendering-big-list-with-purerendermixin

If this feature is released, ReactCSSTransitionGroup won't need a wrapper node anymore right?

@slorber Yes, that's probably true.

Run into the need for this feature everyday.

If you have many small components (ie design very modularly), you end up having to wrap all kinds of things in divs that shouldn't be. I might be conflating, but I think this relates to this issue.

For <div>'s you can wrap them in a <div>, but for table rows <tr> elements, it's not so easy. You can wrap <tr> in <tbody>, but may not be desirable to have multiple layers of <tbody> wrapping multiple layers of <tr>'s.

The scenario I called out was trying to have a component that provides <link> and <script> elements without having to become the <head> renderer entirely.

I added a note to the top of this issue. Please read it before commenting. https://github.com/facebook/react/issues/2127#issue-41668009

Bump...I have a large need for it on the server side. It's very complicated to render full web pages (excluding doctype) without the ability to render fragments, because of the <head> section. I'm currently working around that via mixins and a little logic in the final render, but it would be much simpler if there was support for rendering multiple components.

@impinball you can attempt to write something similar to react-document-title based on react-side-effect to solve these problems. I was able to do the same for meta tags, headers, title and occasionally redirects

I'm hitting this problem as well, are there any workarounds for the time being? I couldn't get {getBunchOfComponents()} to work as suggested.

None other than the ones already mentioned.

@jonchay You could create a component that only renders its children.

function statelessWrapper(props) {
   return props.children;
}

and then to use it:

render() {
   return (  
      <statelessWrapper>
         {renderABunchOfComponents()}
      </statelessWrapper>
    );
}

@whatknight That won't work except in cases that return renderABunchOfComponents(); already works.

  render () {
    let user = this.state.user
    let profile = user.get('data')
    let view = null

    if (user.get('status') === 'fetched') {
      view = (
        <h1>{profile.get('login')}</h1>
        <img src={profile.get('avatar_url')} />
        <dl>
          <dt>email</dt>
          <dd>{profile.get('email')}</dd>
        </dl>
      )
    } else if (user.get('status') === 'fetching') {
      view = <h1>fetching</h1>
    } else if (user.get('status') === 'error') {
      view = <h1>{profile.message}</h1>
    }

    return (
      <div className={className}>
        {view}
      </div>
    )
  }

There should at least be a way to return multiple fragments while doing interpolation and "assembly". The above example is complaining about img and h1 being adiacent but they will end up being inside the main wrapper anyway. That's one wrapper element I wish I could get rid of.

@kilianc in this case, you can simply write

      view = [
        <h1 key={0}>{profile.get('login')}</h1>,
        <img key={1} src={profile.get('avatar_url')} />,
        <dl key={2}>
          <dt>email</dt>
          <dd>{profile.get('email')}</dd>
        </dl>,
      ]

the way you're using it, it won't make a difference if this issue gets resolved.

I need this feature for already-stated reasons, so tried implementing a <frag></frag> container at https://github.com/mwiencek/react/tree/frag-component

The implementation isn't really pretty, but if it works for people I can submit a PR and let the React devs tear it apart.

@mwiencek Looks like your implementation doesn't work if the number of children in a fragment changes in an update (_nestedChildCount is set only in mountComponent)? There's a little trickiness to make that all work well. Looks like you've got a good start though. I've actually been thinking about this again recently and I may have figured out a robust way to make this happen. I'll report back if I find success.

@spicyj yup, you're right, I'll need to look into that...

Super stoked that we might see a proper implementation soon, though. :) Feel free to copy tests from that branch if they're of any use at all.

@spicyj Isn't the way forward to use createFragment and have JSX transform into that? Or do we really want fragments to be elements?

To build and expand on the last comment of @syranide, there seems to be no need for an extra "Fragment API" if render allows for arrays as return value. JSX could transform multiple root elements into an array, which would also work for return values of any other function. So instead of introducing additional API surface, which requires documentation and learning, one of React's limitations could just be removed.

This would at least affect babel-plugin-transform-react-jsx (implementation) and also babel-plugin-syntax-jsx(removing parse error for adjacent root elements). While changing the former seems to be fairly safe, I don't know the scope / usage of the latter and the impact the proposed change would have on other projects.

That still doesn't cover the use case of a conditional with multiple elements. I don't consider "Use an array and manually add an arbitrary key={...} to each element" to be proper a long term solution.

agree with @dantman

yup, good point. Automatic key generation should be built in via the transform. Using the array index as key should suffice, since the items are not changing.

As for conditionals, this could also be built into the transform or alternatively you could use JSX-Control-Statements. Implemented it there in this way, hence the idea.

To handle updates correctly I figured the solution @spicyj thought of for #5753 might work for fragments too (wrapping the contents in something like <!-- react-frag: 1 --><!-- /react-frag: 1 -->). Yeah the comments are a bit ugly, but it's way more reliable than what I was trying to do with _nestedChildCount. That approach is now what's used at https://github.com/mwiencek/react/tree/frag-component

I haven't seen this mentioned in the thread thus-far, but I think solving this also improves composability. For instance, imagine you have a grid where you want the cells to fade in a certain order. Ideally, there'd be two components at play here: one to handle the layout and another to handle the animation. You'd have an API like this:

<GridLayout
  columns = { 3 }
>
  <FadeAnimator
    springConfig = { springConfig }
  >
    { ...cells }
  </FadeAnimator>
</GridLayout>

This would enable you switch to a different layout, or a different animation, without one having to know about the implementation details of the other. GridLayout would expect to receive a list of children. FadeAnimator would intercept that list, inject the appropriate styles and/or event listeners, and return the new list for GridLayout to consume. There's no reason for FadeAnimator to be concerned with laying out a grid, except that React elements can't return Arrays from render. Moreover, there's no simple way to replace the grid with, say, a masonry layout, because FadeAnimator is being required to act as a container for its children.

With the current limitations, I suppose you could do something like this:

<FadeAnimator
  wrapper = {
    <GridLayout
      columns = { 3 }
    />
  }
  springConfig = { springConfig }
>
  { ...cells }
</FadeAnimator>

// FadeAnimator
render() {
  return React.cloneElement(
    props.wrapper,
    null,
    props.children
  );
}

but that makes the code less clear, more complex, and harder to compose.

Add fragment API to allow returning multiple components from render!
Add fragment API to allow returning multiple components from render!
Add fragment API to allow returning multiple components from render!
Add fragment API to allow returning multiple components from render!
Add fragment API to allow returning multiple components from render!
Add fragment API to allow returning multiple components from render!
Add fragment API to allow returning multiple components from render!
Add fragment API to allow returning multiple components from render!

@texttechne suggestion is better. Instead introducing additional API, react should handle multiple root elements in render.

Handling multiple root elements in render would be hard I think.
It means that there: https://github.com/facebook/react/blob/master/src/renderers/shared/reconciler/ReactCompositeComponent.js#L1089

You would have an array of elements rather than an element.
Due to this, as far as I understand it, you'd have now to instantiate multiple React elements: https://github.com/facebook/react/blob/master/src/renderers/shared/reconciler/ReactCompositeComponent.js#L471

Then, mount multiple instantiated React elements: https://github.com/facebook/react/blob/master/src/renderers/shared/reconciler/ReactCompositeComponent.js#L471

And reconcile all the markup produced in the good order.

I think it comes with drawbacks that might not want to get around the reconciliation process.
Do we want to have fragments as elements or fragments as sugar syntax around transformations?

I think that fragment as an element is alright, we'd just need to create a new type of internal node similar to text nodes or empty nodes, right? Though I don't know how we'd manage them.

For instance, how do you handle when one of the roots is unmounted? How do you handle update properly?
Or, how do you manage multiple roots inside of the DevTools? (obvious answer: fix the DevTools...)

I think that a fragment is a composite component. Where is the difference exactly?
If we end up to duplicate code in order to implement fragments, we'd better implement sugar syntax in order to keep the React internals "pristine" ?

I'm wondering, I have been playing around with React internals around the Subtree question (renderSubtreeIntoContainer) and I feel like that it is somewhat related. When you want to render into a new subtree, you will have to render a new root in fact. So, if we support multiple roots at a tree level, do we render new roots each time:

<p>Hi</p>
<p>There</p>

would results in two "render into a new root" call.

Rather than one call if we used a wrapper, right? What about performance? Simplicity? To be honest, my feeling is: we should not touch to React internals to handle this situation. Rather, can we pull out this feat with JSX? Can we improve JSX syntax?

(_Disclaimer_: I'm not totally used to React internals, and there might be some parts that I don't fully understand or that I didn't understand. My apologies for misunderstanding.)

Edit: fixing/clarifying things. Also, GitHub mysteriously styles emails oddly, so I had to reformat the code block... :-(

Hi, core Mithril contributor/committer here.

TL;DR: Fragments are extremely hard, even when the API and internals are
simple.

By the way, I know from experience it's _very_ difficult to implement. This
has also been requested multiple times for Mithril, but declined because of
the sheer difficulty. Every attempt to implement it has failed with at
least a third of the test suite failing.

I'm still working out details on a vdom library I'm planning on writing,
and it will treat everything as a fragment, but this is something you have
to literally (re)write the rendering portion from scratch for. Like React,
it'll be decoupled from the DOM, but the API will significantly differ
conceptually for rendering.

Here's the catch with fragments: you have to manage them completely
internally or you don't properly diff them. Even
document.createContextualFragment is useless. Just as an example, let's
transform two trees, rendering omitted:

// Before
A {}
fragment {
  B[class="foo"] {}
  B[class="bar"] {}
}
C {}
D {}

// After
A {}
B[class="foo"] {}
fragment {
  C {}
}
D {}

The correct transform for this should be to replace both B elements and the C element, leaving the rest untouched. Figuring that out is non-trivial, and you have to basically iterate the fragment's children while ignoring the fact they're in a fragment.

But when the fragment's gone, you have to handle the hook semantics, like
shouldComponentUpdate (I don't remember React's name for that hook). So
you still have to track the fragments independently. You diff their
contents as if they were part of their parent fragment, but you still have
to keep track of that fragment's position for the component's sake.

Or in other words, components are no longer intrinsically linked to their
DOM node. Instead, they're linked to the corresponding fragment. React, like most other vdom libraries and frameworks, intrinsically couple the component to its tree representation, even with the expected types. This is the easiest way to implement a diff algorithm that
handles components. When they are decoupled, you have to do separate
bookkeeping for both. You don't initialize components when you initialize
the node. It's now two completely separate processes. It's hard to do
initially, and even harder to add support for afterwards.

Thanks all for the words. We know this is hard and still have it on our to-do list. (Asking enthusiastically won't make it happen sooner @janryWang.)

@isiahmeadows FYI, Mithril's rewrite branch does support fragments.

@spicyj You're welcome to take a look at the implementation[1][2] and tests[1][2] if you aren't already following it. The whole diff engine is only about 400 LOC, so it should hopefully be easy to follow

@isiahmeadows I think GitHub ate part of your comment. The code block is broken, and I can't see passed the first instance of <D />.

Looks OK in e-mail though. Maybe you found a bug in GitHub?

Unfortunately GitHub's markdown handling behaves differently when a comment comes from an email. I edited the comment to remove a blank line and now it shows up.

I forwarded the original e-mail to support@github. Hopefully, they can fix the parser. 😃

@lhorie You use array syntax for fragment ?
do you have polyfill for DocumentFragment ?

And using a "pseudo" wrapper element, like a HTML comment is not an option? I thought that was the way text nodes where "solved"...

Thanks for fixing that comment @spicyj

To address the concerns @isiahmeadows brought up in his example: the new Mithril engine does _not_ follow the semantics that @isiahmeadows suggested for several reasons:

  • implementing those semantics would make diffing _significantly_ more complex
  • it would make it difficult to reason about keys and key-related bugs since it becomes possible for key spaces to bleed out from components and even into sibling and subchild components.
  • it would make fragment lifecycles non-intuitive (e.g. in that example, B.bar is removed, but so is the fragment, and a new fragment is created to wrap C). This violates the general principle that lifecycles "cascade", meaning that you can no longer be sure that a child node is removed if a given parent node is removed. Like the previous point, this has the potential to cause leakages on the encapsulation capabilities of a component.
  • if, hypothetically, one does run into diff issues related to a diff engine not adhering to those semantics, the application-space solution is as trivial as wrapping a fragment around the offending node.

I'd be interested if the core team could expand on the note at the top re: _why_ this is hard with the current architecture. Seeing that React and Mithril's rendering engine are fundamentally trying to solve the same issues, and that Mithril does now support fragments to a degree that I believe to be feasible and useful, maybe implementing it in React might be more feasible if different aspects of the semantics are assessed separately (and potentially rejected) like it was done with Mithril.

Note that I fixed my comment. I made a few mistakes, and GitHub doesn't do well styling email responses... :frowning:

@Primajin I've wondered that too, but I suspect they'd be passed as one element. It's important to make fragments composable (see my example above). However, there are probably times you'd want to treat them as one unit too.

Perhaps, React.Children.map should expand fragments. If you want to iterate over every child (including children of child fragments), use Children.map. If you want to treat fragments as an opaque box, work directly with props.children as an {array, element}.

@lhorie I haven't been as involved in the rewrite, though, so I'm not as familiar with its intricacies. I've been busy with the fact I have one final this week and three next week, plus I'm working with someone to set up an internship my college requires. I've also been focused on finishing Techtonic, which I _almost_ have the CLI done (a test is broken that shouldn't be).

@isiahmeadows Just a friendly reminder to stay on topic. Feel free to use the mithril gitter room if you want to chat about other topics.

@appsforartists

Perhaps, React.Children.map should expand fragments

Mithril stable does something similar internally (i.e. flattening sub-arrays), but I'm moving away from that model due to perf reasons (and also due to some historical headaches regarding vnode lists that mixed keyed and non-keyed nodes). Might be something to consider.

And using a "pseudo" wrapper element, like a HTML comment is not an option? I thought that was the way text nodes where "solved"...

We've been using https://github.com/mwiencek/react-packages in production for a few months. It uses this comment wrapper approach, so fragments can be unambiguously nested.

@mwiencek It is possible to use yours approach without custom react package?

@mwiencek are the comment wrappers even necessary? I would not expect clever things from fragments, if you move an element out of a fragment into a sibling fragment or the root element, it can just be recreated.

So if you follow the vdom tree in order, you don't need comments, or do you?

Anyway, your solution looks like it's exactly what's needed to resolve this issue, at first glance. 👍

Not strictly, but they made the implementation simpler in this instance.

So essentially it is currently not possible to create proper description lists <dl> with React?

<dl>
  <dt>Def 1</dt>
  <dd>Some description</dd>
  <dt>Def 2</dt>
  <dd>Some other description</dd>
</dl>

@KaiStapel This issue is about returning multiple components (or elements I guess) from render(). As long as your render function only returns one root element / component it should work.

OK:

render() {
  return (
    <dl>
      <dt>Def 1</dt>
      <dd>Some description</dd>
      <dt>Def 2</dt>
      <dd>Some other description</dd>
    </dl>
  )
}

Not OK:

render() {
  return (
    <h2>my list</h2>
    <dl>
      <dt>Def 1</dt>
      <dd>Some description</dd>
      <dt>Def 2</dt>
      <dd>Some other description</dd>
    </dl>
  )
}

@GGAlanSmithee Well hardcoded yes, but you can not do:

<dl>
   loop here and print out dt/dd pairs
</dl>

Which is very sad. Same also goes for tables with rowspans, since you can not render two <tr> elements at once :(

From the top:

"Me too" and "+1" are not valuable, nor are use cases that have already been written in the comments (e.g., we know that you can't put <tr> or <dd> elements with a <div>).

Given that there is a working solution in https://github.com/mwiencek/react-packages, is there any chance this will be part of React proper soon? Or are we waiting on the new reconciler?

Given that there is a working solution in https://github.com/mwiencek/react-packages

Are you using it successfully in real projects?

@mwiencek

The implementation isn't really pretty, but if it works for people I can submit a PR and let the React devs tear it apart.

Sure, please send a PR!

About submitting a PR, the last I heard from @spicyj was that they wanted to finish the new core algorithm and do a proper solution with that, since the comment nodes don't really make sense in React Native. I haven't been following the status of that, but I don't think those plans have changed. I'm glad people find the packages useful in the meantime.

The new algorithm is in the works and supports fragments. However I wouldn’t expect it to become production ready for months to come. I wonder if adding this first to React DOM and later to React Native is too bad? The downside is it fragments the ecosystem a little (pun intended!), but it may give us some time to experiment with that feature. We have a team meeting today so I’ll raise this question if we have time to get a better understanding.

@gaearon Can I just point out that supporting fragments is super simple, it's just sugar, I'm currently using <frag> myself by way of a tiny trivial wrapper. Is returning multiple children as the component root really that important?

@syranide I am using the custom build with frag in the beta environment, however I would like to use official React build instead. Can you provide your <frag> wrapper? :) Thanks

@amertak

import React from 'react';
import createFragment from 'react-addons-create-fragment';

let nativeCreateElement = React.createElement;

React.createElement = function() {
  if (arguments[0] !== 'frag') {
    return nativeCreateElement.apply(this, arguments);
  }

  let length = arguments.length;
  if (length <= 2) {
    return null;
  }

  let children = {};
  for (let i = 2; i < length; i++) {
    children['~' + (i - 2)] = arguments[i];
  }

  return createFragment(children);
};

We talked more about this in the last team meeting. The consensus is that we don’t want to go with this particular implementation. However this feature will be supported in the long term core rewrite (no timeline on this for now).

We will also consider it again as one of the things we could potentially work on for the second half of this year if the rewrite takes too long or doesn’t work out. No guarantees it will make the list but we will keep you all updated if it comes up.

To get a better idea of what we work on, please see our meeting notes repo! You can find our latest discussion on this in https://github.com/reactjs/core-notes/blob/master/2016-07/july-07.md.

@gaearon It would be interesting with traction on having an official frag-syntax at least.

@syranide Thanks for the code, but unfortunately it seems that I cannot use it as I need the frag as the root app component that is being renderer by ReactDOM.render method and this method will not accept fragment.

Thanks anyway, It will be useful for other people that don't need the frag as app root.

@amertak Yes it's only for enabling a more reasonable syntax for creating fragments, it doesn't add any new features.

@syranide
I was thinking If it would be possible to render comment manually and treat is as another component (that might not be necessary)?
Internally comments are handled as #comment type so maybe being able to call
React.createComponent('#comment', { ... }, children)?
Just an idea. Small workaround.

The key thing missing here is being able to render comment node, am I right? :)

@gaearon A bit sad that this isn't coming soon, but I appreciate the transparency. Good write up!

An alternative solution until an update ?
For me, i need render a dropdownmenu of Botstraap

render(){
    return (
        <ButtonNotification/>
        <ul className="dropdown-menu">
            {this.state.items.map(this.addItem)}
        </ul>
    );
}
ReactDOM.render(
    React.createElement(NotificationHandler, null),
    document.getElementById("listNotification")
);

But is not possible, an idea ?
Thanks,

http://getbootstrap.com/components/#btn-dropdowns-single

It is clearly wrapped in a single <div class="btn-group"> as shown in the Docs

Yes of course, but there is two elements wrapped in <div class="btn-group">.

render(){
    return (
        <ButtonNotification/> //ELEMENT 1
        <ul className="dropdown-menu"> //ELEMENT 2
            {this.state.items.map(this.addItem)}
        </ul>
    );
}
ReactDOM.render(
    React.createElement(NotificationHandler, null),
    document.getElementById("listNotification") //is DIV#listNotification
);
<div id="listNotification" class="btn-group"><!--wrap-->
    <a href="#">button notification</a> <!--ELEMENT1-->
    <ul> <!--ELEMENT2-->
        <li></li>
        <li></li>
    </ul>
</div>

And two element wrapped in single element is not possible,
Thanks for your time @Primajin

Just shift everything one level:

render(){
    return (
        <div className="btn-group"> //WRAP
            <ButtonNotification/> //ELEMENT 1
            <ul className="dropdown-menu"> //ELEMENT 2
                {this.state.items.map(this.addItem)}
            </ul>
        </div>
    );
}
ReactDOM.render(
    React.createElement(NotificationHandler, null),
    document.getElementById("listWrapper") //or whatever your list is called
);

Okay, but I have other items in the parent.
This will only move the problem.

<div ...> <--!listWrapper-->
    <div class="btn-group">....</>
    <div class="btn-group">....</>
    <--!React-->
    <div class="btn-group"> //WRAP
        <ButtonNotification/> //ELEMENT 1
        <ul className="dropdown-menu"> //ELEMENT 2
            {this.state.items.map(this.addItem)}
        </ul>
    </div>
    <--!React-->
    <div class="btn-group">....</>
</div>

And in this case, React will replace all contained.
Is it possible to do an "add" without replacing the other elements?

Thanks,

@rifton007 that's not how it works. You can have multiple elements/components as siblings, wrapped in a container. The restriction is that a component cannot return multiple elements. The code you just posted will work.

That being said, if you do come up with an example that doesn't work it is polite to read the entire thread and consider whether or not you are adding a _new_ example or just repeating the same issue that has already been acknowledged. This is a known restriction, and this thread contains an extended discussion of the details and reasoning for the restriction. Dan has also stated they intend to fix support this, eventually. What are you trying to accomplish by pointing to another example for an acknowledged issue?

Sorry, I just wanted to know if anyone would have an alternative solution in the meantime.
You can delete my posts if necessary.

I create app with Framework7 and React, however the framework7 html format is fixed,

<div class="page"><div class="navbar"></div><div class="searchbar"></div><div class="page-content"></div><div class="toolbar"></div></div>

I can not wrap the first level child elements (navbar, searchbar) in other div which not having 'page' class

I have a component that returns a list of rows to be used in a table and I can't wrap them in an additional HTML tag (not allowed by HTML5 standard - I know about tbody but I might have multiple rows returned by multiple child components that may need to be combined into a single tbody). Has the technique mentioned by @Prinzhorn - wrapping those children in an HTML comment - has actually been implemented by anybody? I tried to implement a component that renders just the HTML comment but it doesn't seem to work.

FYI, the rewrite we're working on (#6170) already supports fragments. You can track our progress in #7925 and on http://isfiberreadyyet.com.

The mere fact that <table> element can not render certain elements is reason enough to add this feature in order to be compatible with web APIs.

EDIT: Ah, fragments! Looking forward to them.

@trusktr

As noted in the very first post in this thread:

Note from maintainers:

We know this is an issue and we know exactly what set of problem can be solved. We want this too but it is a hard problem with our current architecture. Additional comments expressing desire for this feature are not helpful.

😉

Gosh dang it, I gotta stop doing that.

I upvoted this but wanted to share a valid use case. Suppose I have 3 buttons which I want a CSS liquid layout (left, center, right). The left button is always visible, but the other two are conditionally visible. In React (specifically React Native), I'm using its flexbox and rendering it as:

[ Left ] { renderCenterAndRightButtons(this.state.someFlag) }

The center and right buttons don't position correctly because they are wrapped in a singular View.

Yes, I could split the center and right buttons to their own methods, but that would introduce a lot of redundant code since they share much behavior.

[ Left ] { renderCenterButton(this.state.someFlag) } { renderRightButton(this.state.someFlag) }

Like it says above, we're already aware of use cases for this feature and are hard at work on supporting it. (There are already a half dozen people above calling out the flexbox issue.) Since it doesn't seem like more discussion will be productive, I'm locking this. We'll update when we have news about the new implementation.

I think we can close this.

Returning arrays from components is supported since React 16 Beta 1 which you can try now.

There are still some limitations (SSR support is not ready) but we’re tracking them in #8854 and will fix before the final 16 release.

Thanks to everyone for your feedback!

THANK YOU DAN

🍾🍾🍾

🦏

@gaearon Awesome improvement! Is it support pure text node?

Yes, it supports returning strings too.

May I ask how is this supposed to work?

I was hoping it would allow us to render 2 adjacent XJS elements but if I do return ["foo", "bar"] (something more useful ;), I get the expected bundle.js:66656 Warning: Each child in an array or iterator should have a unique "key" prop.

So was the feature a way not to surround a real list by an extraneous element?

So was the feature a way not to surround a real list by an extraneous element?

Yes, a way to provide several elements from one render. (For more information, see the initial issue post.)

If all your array items are known to be strings, just join them and return a single string. If not, you can either eat this warning or work out what to do to wrap them in elements so that they can be keyed to improve DOM reconciliation, just as you would have if you had included an array of strings inside another element in JSX.

@diligiant returning ['foo', 'bar'] is not relevant to this issue. You never could and still can't do return <div>{['foo','bar']}</div> Each child in an array should have a 'key' prop whether it's in an internal jsx tag like <div> or it's being returned. What you can do now is:

return [<div key='1'>foo</div>, <span key='2'>bar</span>];

It removes a big limitation in react.

Btw returning ['foo', 'bar'] gives you a warning not an error and to remove that warning you can easily join those strings or if they're jsx tags and not strings you can add a key prop to them. So there's no limitation about returning arrays.

@JesperTreetop thank you.
@sassanh, from your example, it seems that I've been too "shy" to use keys "just" to avoid a surrounding (semantically) useless <div>. Do you mean I should go ahead and that there is no real performance penalty? That would indeed be a REAL improvement!

@diligiant I doubt it introduces any performance penalty but you don't need a surrounding useless div unless it's surrounding strings and if it's surrounding strings you can avoid array at all and join strings. If it's not strings you can add the key to the component. For example if you have two components Foo and Bar you can return [<Foo key='foo'/>, <Bar key='bar'/>] and you don't need to surround neither your components (like always) nor your array (thanks to this new release, you needed to surround the array before 16).

@sassanh cool then. Of course my use case was with multiple components. Happy!! ;)

Actually it seems odd to me that we warn about missing keys when all items are strings. I wouldn't expect us to do so. Is this existing behavior in 15 when strings are inside a div? If not then we should fix it in 16 for top-level strings (since it's impossible to give keys to them).

@gaearon sorry, my example was misleading: I meant components.

I checked and under -beta.5, React doesn't issue a warning when rendering an array with multiple strings.

Nonetheless, I am puzzled by the key requirement when rendering an array just for the sake of avoiding a surrounding component. I understand and it's nothing but it will probably raise tons of questions on SO (I have nothing better to offer though…)

And finally, thank you again.

This warning is the exact same as for every other usage of arrays of components, because it boils down to the exact same "extra work" for the reconciler, and thus the exact same potential optimization by setting a key. To me the surprise would be if arrays of components were to be treated differently depending on this, and I imagine that would prompt some Stack Overflow questions too. Not to mention that I think it would involve some overhead just to keep track of it in the first place.

.. and most of the time I will be returning an array from a function, I do want the key warning in place. It seems the times you wouldn't want the warning are the minority, and there's no way for React to know if it's appropriate to not warn.

The warning is necessary because lack of keys can cause correctness issues, not just performance problems. This is explained in many other issues asking why keys are necessary so I encourage you to search for them and read those discussions. I agree the docs could be clearer about this, and it's something we'll likely look at next time we do a docs change sprint.

There is no conceptual differences between arrays directly returned from render, and arrays inside a div. So there is no reason why there would be a key warning in one case but not the other. They need to work the same way because both are affected by the same problems when the keys are missing.

That said we understand it's annoying to specify keys for static content. Just like you don't specify keys when you write a JSX structure where children are statically known (and thus never reorder), it would be nice to have a way to do this with arrays.

In the future we might solve this by adding explicit support for fragments in JSX with syntax like:

return (
  <>
    <div>child 1</div>
    <div>child 2</div>
  </>
);

It could produce an array but implicitly assign numeric indexes to the children because in this case we know they can never reorder. This guarantee given by JSX child expression is exactly what lets us get away without specifying keys in normal JSX code where a div might have multiple children.

But we don't have this syntax yet. So for now this is a known limitation.

@JesperTreetop & @zwily, @gaearon explained it way better than I did ;)

Once you know, it's no big deal but as we all want React to thrive, I was just saying…

@gaearon Is there another issue for the <> syntax proposal that we can watch instead of further discussion on this issue? I searched around but I wasn't able to find one.

@smrq +1 to question — I follow everything about those awkward limitations (one-to-one rendrer() result, keys and JSX syntax or fragments) but the only ticket I know is https://github.com/facebook/jsx/issues/65

I also suppose that fibers gonna fix issue with keys at all — but looks like it's unfulfilled dream

Keys aren't an "issue". :) They're a fundamental and necessary part of any view framework that allows you to create dynamic lists.

See https://facebook.github.io/react/tutorial/tutorial.html#keys for a more detailed explanation.

@spicyj actually it is an «issue» since it cause extended energy spendings from developers and there is fundamental possibility to program view framework without such requirement (for example https://github.com/dfilatov/vidom)

there is fundamental possibility to program view framework without such requirement (for example https://github.com/dfilatov/vidom)

vidom does use keys in collections though. It might technically work without it but it would likely be much slower. React could also technically work without keys, but it'd be quite unexpected to find that half of your components have to update when you remove a single item from a list. With keys, only one item is unmounted.

@goto-bus-stop vidom can use keys, but they are not required and without them only really big cases with a lot of updates can cause real performance problems

so I consider this part as possible optional (as, for example, shouldComponentUpdate) which can be used for ferformance tweaks in individual cases

@veged example of vidom struggling without keys.

It has no idea it's supposed to reorder the elements, so it discards the instances on each render of the root component.

as someone who's quite familiar with the virtual-dom space [1]. i can say that:

  1. keys are necessary for predictable dom & state updates amongst similar siblings.
  2. keys are typically not an optimization, and - in fact - are usually the opposite.

[1] https://github.com/leeoniya/domvm

however, the unambiguous issue here (as @gaearon described) is a fully static usage of arrays and the difference between static arrays and static JSX fragments

@brigand O have no doubt that reordering of state-full components may cause some issues ;-) but force every other cases (in my opinion more of them) to struggle for this... looks controversial

Keys are important to React. Even if they don't seem to matter in some case (e.g. because components below are all stateless) there is nothing preventing you or someone else on the team to add a stateful component (or even a plain DOM input) somewhere a few levels below in a few months. By then you might forget that you don't have keys, and thus reorders may cause the state (or input value) to be associated with a wrong item.

This is why we encourage you to specify keys everywhere for dynamic lists. Not doing so leads to very hard-to-trace bugs, and we think it's better to spend extra ten seconds specifying the key than ten hours debugging why the state of a component several levels below gets messed up in some corner case.

I fully agree it's inconvenient to specify keys when the list is known to be static and never reorders. You are welcome to discuss this on the JSX repo. If you can't find an issue for this, you are welcome to create a new one there.

Since this thread has a lot of subscribers and the feature has been implemented I would like to lock it to avoid spamming a lot of people with notifications. I hope the clarifications above address your concerns, but if not, you are welcome to create a new issue for further discussion on a specific topic.

@smrq created a proposal issue for <> syntax on the jsx repo: https://github.com/facebook/jsx/issues/84.

We just released support for a new React.Fragment export and the associated <> syntax:
https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html

Was this page helpful?
0 / 5 - 0 ratings