I have this problem. I want to loop an array and display the values as a table where each element is a row in the table. So far, no problems. But depending on a value in each element, I want to show an additional row with more values for each array element. I have this code:
<tbody>
{myList.map((item, i) => {
return (
<div>
<tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
<td className="toggler">
{item.mobile_open && <ArrowUp />}
{!item.mobile_open && <ArrowDown />}
</td>
<td>{item.elem_one}</td>
<td>{item.elem_two}</td>
<td>{item.elem_three}</td>
</tr>
{item.mobile_open &&
<tr className="test-td">
<td>...</td>
</tr>
}
</div>
);
})}
</tbody>
My problem is that I get:
Warning: validateDOMNesting(...): Text nodes cannot appear as a child of <tr>.
and
Warning: validateDOMNesting(...): <div> cannot appear as a child of <tbody>
When I try the above approach. Removing the div gives me Syntax error
which I already knew but tried anyway.
Does anyone have an idea how to solve this?
You're doing
{item.mobile_open &&
<tr className="test-td">
<td>...</td>
</tr>
}
that prints false like <tr>false</tr>
if mobile_open is false.
try
{item.mobile_open ?
(<tr className="test-td">
<td>...</td>
</tr>) : null
}
As for the div warning consider using React 16 Fragments
using React 16.0 fragment syntax
<tbody>
{myList.map((item, i) => {
return [
<tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
<td className="toggler">
{item.mobile_open && <ArrowUp />}
{!item.mobile_open && <ArrowDown />}
</td>
<td>{item.elem_one}</td>
<td>{item.elem_two}</td>
<td>{item.elem_three}</td>
</tr>,
{item.mobile_open &&
<tr className="test-td">
<td>...</td>
</tr>
}
];
})}
</tbody>
But I prefer the most recent React 16.2 Fragment Syntax
import React, { Fragment } from "react";
<tbody>
{myList.map((item, i) => {
return (
<Fragment>
<tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
<td className="toggler">
{item.mobile_open && <ArrowUp />}
{!item.mobile_open && <ArrowDown />}
</td>
<td>{item.elem_one}</td>
<td>{item.elem_two}</td>
<td>{item.elem_three}</td>
</tr>
{item.mobile_open &&
<tr className="test-td">
<td>...</td>
</tr>
}
</Fragment>
);
})}
</tbody>
More on fragments here
In React16 you are now able to return an array of components allowing you to remove the <div />
.
The code would look something like :
<tbody>
{myList.map((item, i) => {
return [
<tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
<td className="toggler">
{item.mobile_open && <ArrowUp />}
{!item.mobile_open && <ArrowDown />}
</td>
<td>{item.elem_one}</td>
<td>{item.elem_two}</td>
<td>{item.elem_three}</td>
</tr>,
//This inline conditional makes it weird but this works
...[item.mobile_open &&
<tr className="test-td">
<td>...</td>
</tr>
]
];
})}
</tbody>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With