Warning: validateDOMNesting(…): <div> cannot appear as a child of <tbody>

匿名 (未验证) 提交于 2019-12-03 01:38:01

问题:

I'm creating a table in react (new to react), but the CategoryData is not creating cells correctly, i.e. it's creating cells that are not aligned with the <th> that come from the parent and they do not have cell borders at all. It's also giving these warnings:

Warning: validateDOMNesting(...): <div> cannot appear as a child of <tbody>. See Param > tbody > Row > div. Warning: validateDOMNesting(...): <tr> cannot appear as a child of <div>. See Row > div > tr. Warning: validateDOMNesting(...): <tr> cannot appear as a child of <div>. See CategoryData > div > tr. 

I'm not sure why this warnings are happening and why the table cells(from CategoryData) are not getting aligned and don't have cell borders. What's the correct way to do it ?

Code

var Param = React.createClass({      getInitialState: function() {         return {             isLoading: true,             panelTitle: "",             data: [],             categories: []         }     },      updateState: function() {         var that = this;         var categories = new Set();         rest.getParameters('service').then(function (results) {             for (var i = 0; i < results.data.length; i++) {                 categories.add(results.data[i].category);             }             that.setState({                 data: results.data,                 categories: Array.from(categories)             })         }).catch(function (err) {             console.error('rest.getParameters(): ', err);             that.setState({                 isLoading: true,                 data: [],                 categories: []             })         });     },      componentDidMount: function() {         this.updateState();     },      render: function() {       return (         <Panel className="panel-info" header={<h4 className="panel-title">Service Config</h4>}>             <div>                 <table className="table table-striped table-bordered table-hover table-condensed table-responsive">                     <thead>                         <tr>                             <th className="col-lg-2 text-center">AMP Name</th>                             <th className="col-lg-2 text-center">Athena Name</th>                             <th className="col-lg-2 text-center">Description</th>                             <th className="col-lg-1 text-center">Default</th>                             <th className="col-lg-1 text-center">Min Value</th>                             <th className="col-lg-1 text-center">Max Value</th>                             <th className="col-lg-1 text-center">Action</th>                         </tr>                     </thead>                     <tbody>                         {this.state.categories.map((category, index) =>                             <th colSpan="7" key={index} style={{'textAlign':'left', 'paddingLeft':'5px', 'backgroundColor': '#D3D0CF'}}>{this.state.category}</th>                             this.state.data.map((row, i) =>                                 if (row.category === category) {                                     <tr key={i}>                                         <td className="col-lg-2 text-center">{row.name}</td>                                         <td className="col-lg-2 text-center">{row.alias}</td>                                         <td className="col-lg-2 text-center">{row.description}</td>                                         <td className="col-lg-1 text-center">{row.default_value}</td>                                         <td className="col-lg-1 text-center">{row.min_value}</td>                                         <td className="col-lg-1 text-center">{row.max_value}</td>                                         <td className="col-lg-1 text-center">Action</td>                                     </tr>                                 }                             )                           )}                     </tbody>                 </table>             </div>         </Panel>     );   } }); 

回答1:

I would change the 'th' to a 'tr' because I'm pretty sure react will give you a warning if you add 'th' inside 'tbody'

let finalList = [] this.state.categories.forEach( (cat, index) => {    finalList.push(<tr...>{this.state.category}</tr>)    this.state.data.forEach( (row, index) => {       if(row.category === cat){          finalList.push(              <tr key={i}>                  <td className="col-lg-2 text-center">{row.name}</td>                  <td className="col-lg-2 text-center">{row.alias}</td>                  <td className="col-lg-2 text-center">{row.description}</td>                  <td className="col-lg-1 text-center">{row.default_value}</td>                  <td className="col-lg-1 text-center">{row.min_value}</td>                  <td className="col-lg-1 text-center">{row.max_value}</td>                  <td className="col-lg-1 text-center">Action</td>              </tr>           )       }    }) }) 

Word of warning I would avoid using tables checkout css grids their a lot more flexible and pretty well supported



回答2:

EDIT: From version 16.0.0 onwards in react, you could make use of React.Fragment to return multiple elements from render

<tbody>     {         this.state.categories.map((category, index) => {             var innerData = this.state.data.map((row, i) => {                 if (row.category === category) {                     return (                         <tr key={i}>                             <td className="col-lg-2 text-center">{row.name}</td>                             <td className="col-lg-2 text-center">{row.alias}</td>                             <td className="col-lg-2 text-center">{row.description}</td>                             <td className="col-lg-1 text-center">{row.default_value}</td>                             <td className="col-lg-1 text-center">{row.min_value}</td>                             <td className="col-lg-1 text-center">{row.max_value}</td>                             <td className="col-lg-1 text-center">Action</td>                         </tr>                     )                 }                 return null             })              return (               <React.Fragment>                 <th colSpan="7" key={index} style={{                     'textAlign': 'left',                     'paddingLeft': '5px',                     'backgroundColor': '#D3D0CF'                 }}>{this.state.category}</th>,                 {innerData}               </React.Fragment>                 )         })     }     </tbody> 

Before v16

With the help of JSX syntactic sugar it is possible to return multiple elements from within a component, by writing them as comma separated elements in an array like

<tbody> {     this.state.categories.map((category, index) => {         var innerData = this.state.data.map((row, i) => {             if (row.category === category) {                 return (                     <tr key={i}>                         <td className="col-lg-2 text-center">{row.name}</td>                         <td className="col-lg-2 text-center">{row.alias}</td>                         <td className="col-lg-2 text-center">{row.description}</td>                         <td className="col-lg-1 text-center">{row.default_value}</td>                         <td className="col-lg-1 text-center">{row.min_value}</td>                         <td className="col-lg-1 text-center">{row.max_value}</td>                         <td className="col-lg-1 text-center">Action</td>                     </tr>                 )             }             return null         })          return ([             <th colSpan="7" key={index} style={{                 'textAlign': 'left',                 'paddingLeft': '5px',                 'backgroundColor': '#D3D0CF'             }}>{this.state.category}</th>,             [...innerData]         ])     }) } </tbody> 

Also when you make use of if statements within a map function, you need to have them outside of the return statement, now if you do {this.state.categories.map((category, index) => <tr>... it means that whatever is after the arrow is considered to be part of the return and hence you inner map's if statement will give you an error.

There is an issue on react github page for returning multiple elements. Read through it for more details.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!