如何包装一个返回多个表行的React组件,并避免"<tr>不能显示为<div>的子项"错误?

Ped*_*ram 46 javascript reactjs

我有一个名为OrderItem的组件,它接受一个包含多个对象(至少两个)的对象,并将它们呈现为表中的多个行.表中将有多个OrderItem组件.问题是在组件的渲染功能中,我不能返回多行.我只能返回一个组件,如果我将它们包装在一个div中,它会说" <tr>不能作为一个孩子出现<div>"

代码看起来像这样(为了更容易阅读,我留下了一些东西)

Parent() {
  render() {
    return (
      <table>
        <tbody>
          {
            _.map(this.state.orderItems, (value, key) => {
              return <OrderItem value={value} myKey={key}/>
            })
          }
        </tbody>
      </table>
    )
  }
}

class OrderItem extends React.Component {
  render() {
    return (
      <div> // <-- problematic div
        <tr key={this.props.myKey}>
          <td> Table {this.props.value[0].table}</td>
          <td> Item </td>
          <td> Option </td>
        </tr>
        {this.props.value.map((item, index) => {
          if (index > 0) { // skip the first element since it's already used above
            return (
              <tr key={this.props.myKey + index.toString()}>
                <td><img src={item.image} alt={item.name} width="50"/> {item.name}</td>
                <td>{item.selectedOption}</td>
              </tr>
            )
          }
        })}
      </div>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法可以返回那些多行并让它们在同一个表中而不将它们包装在div中并得到错误?我意识到我可以为每个组件创建一个单独的表,但这会使我的格式稍微抛出.

tre*_*rgk 29

是!!可以将项映射到表中的多个表行.不抛出控制台错误并且在语义上实际上是正确的解决方案是使用tbody元素作为根组件并根据需要填充尽可能多的行.

items.map(item => (
   <tbody>
       <tr>...</tr>
       <tr>...</tr>
   </tbody>
))
Run Code Online (Sandbox Code Playgroud)

以下帖子涉及有关它的道德问题,并解释了为什么我们可以使用多个tbody元素 我们可以在同一个<table>中有多个<tbody>吗?

  • 为了记录,这在当时似乎是一个好主意,但在反应16中,我们可以而且应该使用碎片代替. (2认同)

Ees*_*esa 19

React 16现在可以在这里进行救援,您现在可以使用它React.Fragment来渲染元素列表而不将其包装到父元素中.你可以这样做:

render() {
  return (
    <React.Fragment>
      <tr>
        ...
      </tr>
    </React.Fragment>
  );
}
Run Code Online (Sandbox Code Playgroud)

  • 从我的经验来看,```&lt;React.Fragment&gt;```似乎比```&lt;tbody&gt;```要好得多。 (2认同)

Jom*_*rio 13

一种方法是OrderItem分成两个组件,将渲染逻辑移动到一个方法中Parent.renderOrderItems:

class Parent extends React.Component {
  renderOrderItems() {
    const rows = []
    for (let orderItem of this.state.orderItems) {
      const values = orderItem.value.slice(0)
      const headerValue = values.shift()
      rows.push(
        <OrderItemHeaderRow table={headerValue.table} key={orderItem.key} />
      )
      values.forEach((item, index) => {
        rows.push(
          <OrderItemRow item={item} key={orderItem.key + index.toString()} />
        )
      })
    }
    return rows
  }
  render() {
    return (
      <table>
        <tbody>
          { this.renderOrderItems() }
        </tbody>
      </table>
    )
  }
}

class OrderItemHeaderRow extends React.Component {
  render() {
    return (
      <tr>
        <td> Table {this.props.table}</td>
        <td> Item </td>
        <td> Option </td>
      </tr>
    )
  }
}

class OrderItemRow extends React.Component {
  render() {
    const { item } = this.props
    return (
      <tr>
        <td>
          <img src={item.image} alt={item.name} width="50"/>
          {item.name}
        </td>
        <td>
          {item.selectedOption}
        </td>
      </tr>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)


Ped*_*ram 4

似乎没有办法将它们干净地包装起来,所以更简单的解决方案是将整个表格放在组件中,然后有多个表格并弄清楚格式。

Parent() {
   render() {
       return (
           {_.map(this.state.orderItems, (value, key) => {
               return <OrderItem value={value} myKey={key} key={key}/>
           })}
       )
   }
}


class OrderItem extends React.Component {
    render() {
        return (
            <table>
                <tbody>
                   <tr>
                       <td> Table {this.props.value[0].table}</td>
                       <td> Item </td>
                       <td> Option </td>
                    </tr>
                    {this.props.value.map((item, index) => {
                        if (index > 0) { // skip the first element since it's already used above
                            return (
                                <tr key={this.props.myKey + index.toString()}>
                                    <td> <img src={item.image} alt={item.name} width="50"/> {item.name}</td>  
                                    <td>{item.selectedOption}</td>
                                </tr>
                            )
                        }
                    })}
                </tbody>
            </table>
        )
    }
}
Run Code Online (Sandbox Code Playgroud)