How do I render sibling elements without wrapping them in a parent tag?
In most cases, having a parent tag isn't an issue.
React.createClass({
render: function() {
return (
<tbody>
<tr><td>Item 1</td></tr>
<tr><td>Item 2</td></tr>
</tbody>
);
}
});
But there are some cases where it makes sense to have sibling elements in one render function without a parent, and especially in the case of a table, you don't want to wrap a table row in a div
.
React.createClass({
render: function() {
return (
<tr><td>Item 1</td></tr>
<tr><td>Item 2</td></tr>
);
}
});
The second example gives the following error: Adjacent XJS elements must be wrapped in an enclosing tag while parsing file
.
How can I render two sibling elements without wrapping them in a <div>
or something similar?
Solution 1:
This is a limitation currently, but will likely be fixed at some point in the future (there's some open issues on the github repo).
For now, you can use a function which returns an array (this is basically a stateless component):
function things(arg, onWhatever){
return [
<tr><td>Item 1</td></tr>,
<tr><td>Item 2</td></tr>
];
}
And use that in your component.
return (
<table><tbody>
{things(arg1, this.handleWhatever)}
{things(arg2, this.handleWhatever)}
</tbody></table>
);
Update
In React 16 you will be able to return an array from render.
Another Update
You can now either return a top level array, or use <React.Fragment>
.
With an array we need to place a key on each item, as React doesn't know that the two elements are constant, instead of a dynamically created list:
function RowPair() {
return [
<tr key="first"><td>First</td></tr>,
<tr key="second"><td>Second</td></tr>,
]
}
With React.Fragment
, it behaves much more like wrapping it in a <div>
or similar, where a key
isn't required if we're not building the children dynamically. First, we can wrap the array in a Fragment:
function RowPair() {
return <React.Fragment>{[
<tr key="first"><td>First</td></tr>,
<tr key="second"><td>Second</td></tr>,
]}</React.Fragment>
}
And then we can eliminate the array and key
s entirely:
function RowPair() {
return <React.Fragment>
<tr><td>First</td></tr>
<tr><td>Second</td></tr>
</React.Fragment>
}
Solution 2:
I know this has been an old post, but maybe my answer could be a help for newbies like me.
In React 16.2, improved support for Fragments was added.
You can now return it like this:
return (
<>
<tr><td>Item 1</td></tr>
<tr><td>Item 2</td></tr>
</>
);
You can wrap it with <></>
or <Fragment></Fragment>
.
If you would like to pass some attributes, only key is supported at the time of writing, and you'll have to use <Fragment />
since the short syntax <></>
doesn't accept attributes.
Note: If you are going to use the short syntax, make sure that you are using Babel 7.
Source Reference
Solution 3:
Woohoo! The React team finally added this feature. As of React v16.0, you can do:
render() {
// No need to wrap list items in an extra element!
return [
// Don't forget the keys :)
<tr key="a"><td>Item 1</td></tr>,
<tr key="b"><td>Item 2</td></tr>
];
}
See the full blog post explaining "New render return types: fragments and strings" here.
Solution 4:
Having a parent element is helpful in most cases, as for example, you can have a parent className which can target children elements style and a few other scenarios...
But, if you really don't want to do that, you can use React.Fragment
So simply do something like this:
<React.Fragment>
<First />
<Second />
<Third />
</React.Fragment>
From version 16.2, there is a shortened version also using <>
, which look like this in render function:
render() {
return (
<>
<First />
<Second />
<Third />
</>
);
}
Also, if using version 16.0 and above, you can return array of elements which doesn't need parent wrapper also like below:
render() {
return [
<h1 key="heading">Hello from Alireza!</h1>,
<p key="first">Here where I'm!</p>,
<p key="second">And again here :)</p>
];
}
Solution 5:
We can render two sibling components by wrapping them inside React.Fragment
. For e.g.
ReactDOM.render(
<React.Fragment>
<Item1/>
<Item2/>
</React.Fragment>,document.getElementById('root')
);
There is even a shorter hand for this though.
ReactDOM.render(
<>
<Item1/>
<Item2/>
</>,document.getElementById('root')
);
Wrapping the components inside the React.Fragment
does not add extra nodes to DOM.