How do I render sibling elements without wrapping them in a parent tag?
ReactjsReactjs Problem Overview
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?
Reactjs Solutions
Solution 1 - Reactjs
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 - Reactjs
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.
Solution 3 - Reactjs
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 - Reactjs
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 - Reactjs
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.
Solution 6 - Reactjs
You can wrap it to the brackets like this:
React.createClass({
render: function() {
return (
[
<tr><td>Item 1</td></tr>
<tr><td>Item 2</td></tr>
]
);
}
});
Solution 7 - Reactjs
This example is work well for me:
let values = [];
if (props.Values){
values = [
<tr key={1}>
<td>props.Values[0].SomeValue</td>
</tr>
,
<tr key={2}>
<td>props.Values[1].SomeValue</td>
</tr>
];
}
return (
<table className="no-border-table table">
<tbody>
<tr>
<th>Some text</th>
</tr>
{values}
</tbody>
</table>
)
Solution 8 - Reactjs
Something like this syntax worked for me
this.props.map((data,index)=>{return( [ <tr>....</tr>,<tr>....</tr>];)});
Solution 9 - Reactjs
For those, who uses TypeScript, the correct syntax is:
return [
(
<div>Foo</div>
),
(
<div>Bar</div>
)
];