简体   繁体   中英

React js: Invariant Violation: processUpdates() when rendering a table with a different number of child rows

I am getting the following error when my react component is re-rendered after a click event:

Uncaught Error: Invariant Violation: processUpdates(): Unable to find child 2 of element. This probably means the DOM was unexpectedly mutated ...

This only happens when my table has a different number of rows than the previously rendered version. For example:

/** @jsx React.DOM */

React = require('react');

var _ = require("underscore");

var testComp = React.createClass({

  getInitialState: function () {
    return { 
      collapsed: false
    };
  },

  handleCollapseClick: function(){
    this.setState({collapsed: !this.state.collapsed});
  },

  render: function() {

    var rows = [
      <tr onClick={this.handleCollapseClick}><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
    ];

    if(!this.state.collapsed){
      rows.push(<tr><th>Row1 1</th><th>Row1 2</th><th>Row1 3</th></tr>);
    }

    rows.push(<tr><th>Footer 1</th><th>Footer 2</th><th>Footer 3</th></tr>);

    return  <div>
                <table>
                    {rows}
                </table>
            </div>
  }

});

module.exports = testComp

If I render different content, but with the same number of rows, I don't get the error, so if I update the if statement to:

if(!this.state.collapsed){
  rows.push(<tr><th>Row1 1</th><th>Row1 2</th><th>Row1 3</th></tr>);
}else{
  rows.push(<tr><th>Row2 1</th><th>Row2 2</th><th>Row2 3</th></tr>);
}

... everything works.

Do I need to force react to re-render the entire component in this case, instead of just the 'changed' elements?

You should read the full error message (at least that's what I am seeing):

Unable to find child 2 of element. This probably means the DOM was unexpectedly mutated (eg, by the browser), usually due to forgetting a <tbody> when using tables, nesting tags like <form> , <p> , or <a> , or using non-SVG elements in an parent.

Every table needs a <tbody> element. If it doesn't exist, the browser will add it. However, React doesn't work if the DOM is manipulated from the outside.

Related: Removing row from table results in TypeError

I encountered this when dealing with p tags. I had nested paragraphs within paragraphs.

To resolve the problem I replaced the wrapping p element with a div element.

Before:

render: function render() {
    return (
        <p>
            <p>1</p>
            <p>2</p>
        </p>
    );
}

After:

render: function render() {
    return (
        <div>
            <p>1</p>
            <p>2</p>
        </div>
    );
}

For people who are using react-templates:

You have to generate the <tbody> tag in the .jsx file. If you only add it in the .rt file you still get the error message.

this.tbody = <tbody>{tablerows}</tbody> // - in .jsx

In My case the fix is to remove spaces in Table render from

<tbody> {rows} </tbody>

to

<tbody>{rows}</tbody>

I think your problem is with using the <th> tag in multiple rows. <th> is reserved for the header row. Try replacing it with <td> everywhere except in the first row. Also you should wrap the header in a <thead> tag and the rest in a <tbody> tag:

var header = [
  <tr onClick={this.handleCollapseClick}><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
];

var body = [];
if(!this.state.collapsed){
  body.push(<tr><td>Row1 1</td><td>Row1 2</td><td>Row1 3</td></tr>);
}

body.push(<tr><td>Footer 1</td><td>Footer 2</td><td>Footer 3</td></tr>);

 return <div>
     <table>
         <thead>{header}</thead>
         <tbody>{body}</tbody>
     </table>
 </div>;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM