Bizon4ik
Bizon4ik

Reputation: 2764

React: validateDOMNesting: #text cannot appear as a child of <tr>

Can you explain me why react show warning Warning: validateDOMNesting(...): #text cannot appear as a child of <tr>. See Router > RouterContext > CarWashPage > AllCarWashTable > tr > #text.? I don't see any text inside tag tr

Code that renders table

export default class AllCarWashTable extends React.Component{

constructor(props) {
    super(props);
    this.generateHeaders = this.generateHeaders.bind(this);
    this.generateRows = this.generateRows.bind(this);
};

static propTypes = {
    cols : React.PropTypes.array.isRequired,
    rows : React.PropTypes.array.isRequired
}

generateHeaders() {
    let cols = this.props.cols;  // [{key, label}]
    return cols.map(function(colData) {
        return <th key={colData.key}> {colData.label} </th>;
    });
}

generateRows() {
    let cols = this.props.cols,  // [{key, label}]
        data = this.props.rows;
    if (this.props.rows.length > 0) {
        return data.map(function(item) {
            var cells = cols.map(function(colData) {
                return <td key={colData.key}> {item[colData.key]} </td>;
            });
            return <tr key={item.id}> {cells} </tr>;
        });
    }
}

render(){
    let headers = this.generateHeaders();
    let rows = this.generateRows();

    return (
         <table className="table table-hove">
             <thead>
                <tr>
                    {headers}
                </tr>
             </thead>
             <tbody>
                    {rows}
             </tbody>

         </table>
    )
}
}

At the end, my table has the following structure

enter image description here

Where is the problem?

Upvotes: 82

Views: 132835

Answers (19)

Akaisteph7
Akaisteph7

Reputation: 6476

This can happen for any of the following reasons:

  1. Displaying a blank ('') or false instead of null
let foo = '';
...
<tr><td>{foo}</td></tr>}
...

OR

let foo = null;
...
{foo && (<tr><td>{foo}</td></tr>)}
...

OR

let foos = [];
...
{foos.length && foos.map((foo) => (
  <tr><td>{foo}</td></tr>
)}
...
  1. Having an extra space
...
{foo ? (<tr><td> {foo} </td></tr>) : null}
...
  1. Using the wrong tag
...
{foo ? (<tr><tr>{foo}</tr></tr>) : null}
...

Correct methods
...
<tr><td>{foo || null}</td></tr>

{/* OR */}

{foos.map((foo) => (
  <tr><td>{foo}</td></tr>
)}

{/* OR */}

{foo ? (<tr><td>{foo}</td></tr>) : null}
...

Upvotes: 0

Conner Fissell
Conner Fissell

Reputation: 1

For my situation, I was getting this error because I forgot to update a SQL query to include an updated column name. The original query was trying to access a column that didn't exist.

This query was being used with Nextjs, React, Material UI and sent to a PostgreSQL server in order to load up a MUI front-end table with database information from the table.

Updating the query fixed the issue.

Upvotes: 0

MD SHAYON
MD SHAYON

Reputation: 8055

You shouldn't pass an unexpected element in the table body tag. You should use tr and td

In your rows would return the element with tr and td

{rows}

Something like

return(
    <tr>
        <td> 
            Hello
        </td>
    </tr>
)

Upvotes: 0

Elchin
Elchin

Reputation: 105

Removing the comment is what helped me too enter image description here

Upvotes: 2

MisterJacket
MisterJacket

Reputation: 82

Kevin Law (from other comment) said that you can do this:

{
  foo ? (<tr><td>{foo}</td></tr>) : null
}

But you can also fix it like this:

{
  Boolean(foo) && <tr><td>{foo}</td></tr>
}

Upvotes: 3

neonidian
neonidian

Reputation: 1263

A <tr> HTML tag indicates a table row. So, any text to be displayed inside a table row must be placed inside <td> HTML tag. This would remove the error.

Example:

return (
    <tr>
        <td> {/* Using <td> inside <tr> */}
            Hello World!
        </td>
    </tr>
);

Upvotes: 7

Mike D3ViD Tyson
Mike D3ViD Tyson

Reputation: 1771

Make sure the let variables are valued otherwise initialize a new empty array.

{headers ? headers : []}

or

{rows || []}

For me it works like a charm ...

render(){
    let headers = this.generateHeaders();
    let rows = this.generateRows();

    return (
         <table className="table table-hove">
             <thead>
                <tr>
                    {headers ? headers : []}
                </tr>
             </thead>
             <tbody>
                    {rows || []}
             </tbody>

         </table>
    )
}

also || null can solve it. the important is that the value is not ''

Upvotes: 2

Yago Gehres
Yago Gehres

Reputation: 69

It's very easy to find. Just open your inspect and look for tag. It should appear at the beginning or at the end of the tag a quoted string like this:

Inspect element  on google chrome

Upvotes: 0

svirins
svirins

Reputation: 151

in my case initialize a variable with null instead of "" works fine

Upvotes: 1

ACV
ACV

Reputation: 10562

In my case I indeed had a <tr> inside a <tr> (intended to use <td>) :)

Upvotes: 0

Yigit Alparslan
Yigit Alparslan

Reputation: 1397

I received this warning when I put text inside <tr> element with no <td> elements. I wrapped my text with <td> elements and the warning disappeared.

When I did this, having a whitespace in my text or having used {} didn't matter.

Upvotes: 0

paulzmuda
paulzmuda

Reputation: 181

Incase anyone else comes across this error or a similar whitespace error with Material UI in React, my solution after hours of breaking my code was a simple javascript comment inside of my table.

 { /*  sortable here */ }

I removed that from between my table elements and the warning disappeared.

Upvotes: 2

Kevin Law
Kevin Law

Reputation: 4070

This will also happens when using logical AND short-circuit && to show/hide conditional rows:

{
  foo && (<tr><td>{foo}</td></tr>)
}

change it to ternary a ? b : c form where c is null will fix it

{
  foo ? (<tr><td>{foo}</td></tr>) : null
}

Upvotes: 102

Jarno Argillander
Jarno Argillander

Reputation: 5945

The accepted answer wasn't the root cause in my case. I got the same warning when I had a comment after <th> tag. The warning went away when I removed the comment.

const TableHeaders = (props) => (
  <tr>
    <th>ID</th> {/* TODO: I had a comment like this */}
  </tr>
)

EDIT: Removing the space between </th> and {/* will also do the trick.

Upvotes: 15

northernwind
northernwind

Reputation: 637

In my case where was an empty '' output (w\o space inside)

<tbody>
  {this.props.orders.map(
    order =>this.props.selectedAgent === order.agent ? 
      <Row item={order} key={ order._id } /> : ''
    )
  }
</tbody>

The null does the trick:

<tbody>
  {this.props.orders.map(
    order =>this.props.selectedAgent === order.agent ? 
      <Row item={order} key={ order._id } /> : null
    )
  }
</tbody>

Upvotes: 32

Notification warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of <tbody>. Make sure you don't have any extra white space between tags on each line of your source code. In my case, initialize variable should NOT is null.

 let elementCart = ''; {/* in the here,warning will append  */}
    if(productsCart.length > 0){
        elementCart = productsCart.map((item, index) => {
            return <CartItem item={item} key={index} index={index} />
        });
    }

    return(
        <tbody id="my-cart-body">
            {elementCart}
        </tbody>
    )

Solution: let elementCart = null;

Upvotes: 4

lukeaus
lukeaus

Reputation: 12255

I received this warning when I had a parenthesis instead of a curly bracket

<table>
  <tbody>
    <tr>
      (showMsg && <td>Hi</td>} // leading '(' should be a '{'
    </td>
  </tbody>
</table>

Upvotes: 0

Blue
Blue

Reputation: 22911

In addition to @Jarno's answer, I also ran into this issue as well. Double check that you don't have any additional } or { at the end of your javascript code:

{this.props.headers.map(header => <th key={header}>{header}</th>)}}
                                                                  ↑

Upvotes: 0

tobiasandersen
tobiasandersen

Reputation: 8680

The problem is the spaces in this line:

return <tr key={item.id}> {cells} </tr>;

It might seem silly, but you're actually rendering the cells and some whitespace (i.e. text). It should look like this:

return <tr key={item.id}>{cells}</tr>;

Upvotes: 93

Related Questions