Rendering and Grouping using React Tables

huangapple go评论54阅读模式
英文:

Rendering and Grouping using React Tables

问题

以下是您要翻译的部分:

I am creating a dynamic table using react based on objects.

The problem is that I am trying to render a new row for every three TD, but instead it is rendering all TDs in the same table row (tr).

How can I separate the TDs into a new TR after a group of 3 TDs have been filled?

Here is my code:

Component rendering table:

export class Roster extends React.Component{
    
    render(){
        return(
            <div id="tab">
                <table >
                    <tbody>
                        <tr>
                            <td colSpan={3}>
                                <h4>Goalkeepers</h4>
                            </td>
                        </tr>
                    </tbody>

                    <Goalies/>
                </table>
            </div>
        )
    }
}

Component looping through object:

class Goalies extends React.Component{

    getTable() {
        let td_array = [];
        let goal_object = {};

        Object.keys(goalies).forEach(function(key) {
            goal_object = (goalies[key]);
          });

        for(const checker in goal_object){
            td_array.push(<td key={checker}>{goal_object[checker].p_name} <br/> {goal_object[checker].city} <br/> {goal_object[checker].number}</td>);
        }

        return(
            <tr>
                {td_array}
            </tr>
        )
    }

      render() {
        return (<tbody>{this.getTable()}</tbody>)
      }
}

Objects:

export const def = {
    1:{
        p_name:"p1",
        number: 2,
        city: "city1"
    },

    2:{
        p_name:"p2",
        number: 5,
        city: "city2"
    },

    3:{
        p_name:"p3",
        number: 3,
        city: "city3"
    },

    4:{
        p_name:"p4",
        number: 7,
        city: "city4"
    },

    5:{
        p_name:"p5",
        number: 15,
        city: "city5"
    },

    6:{
        p_name:"p6",
        number: 21,
        city: "city6"
    }
}

I want to get:

td1 td2 td3
td4 td5 td6

instead, I am getting:

| td1 | td2 | td3 | td4 | td5 | td6 |
|:---- |:------:| -----:|

英文:

I am creating a dynamic table using react based on objects.

The problem is that I am trying to render a new row for every three TD, but instead it is rendering all TDs in the same table row (tr).

How can I separate the TDs into az new TR after a group of 3 TDs have been filled?

Here is my code:

Component rendering table:

`export class Roster extends React.Component{

render(){
    return(
        &lt;div id=&quot;tab&quot;&gt;
            &lt;table &gt;
                &lt;tbody&gt;
                    &lt;tr&gt;
                        &lt;td colSpan={3}&gt;
                            &lt;h4&gt;Goalkeepers&lt;/h4&gt;
                        &lt;/td&gt;
                    &lt;/tr&gt;
                &lt;/tbody&gt;

                &lt;Goalies/&gt;
        &lt;/div&gt;
    )
}

}`

Component looping through object:

`class Goalies extends React.Component{

getTable() {
    let td_array = [];
    let goal_object = {};

    Object.keys(goalies).forEach(function(key) {
        goal_object = (goalies[key]);
      });

    for(const checker in goal_object){
        td_array.push(&lt;td key={checker}&gt;{goal_object[checker].p_name} &lt;br/&gt; {goal_object[checker].city} &lt;br/&gt; {goal_object[checker].number}&lt;/td&gt;);
    }

    return(
        &lt;tr&gt;
            {td_array}
        &lt;/tr&gt;
    )
}

  render() {
    return (&lt;tbody&gt;{this.getTable()}&lt;/tbody&gt;)
  }

}`

Objects:

export const def = {
1:{
p_name:"p1",
number: 2,
city: "city1"
},

2:{
    p_name:&quot;p2&quot;,
    number: 5,
    city: &quot;city2&quot;
},

3:{
    p_name:&quot;p3&quot;,
    number: 3,
    city: &quot;city3&quot;
},

4:{
    p_name:&quot;p4&quot;,
    number: 7,
    city: &quot;city4&quot;
},

5:{
    p_name:&quot;p5&quot;,
    number: 15,
    city: &quot;city5&quot;
},

6:{
    p_name:&quot;p6&quot;,
    number: 21,
    city: &quot;city6&quot;
}

}

I want to get:

td1 td2 td3
td4 td5 td6

instead, I am getting:

| td1 | td2 | td3 | td4 | td5 | td6 |
|:---- |:------:| -----:|

I tried using conditional statements, pushing into a new array...

答案1

得分: 0

为了实现您想要的布局,正确的HTML标记如下所示:

<table>
  <thead>
    <tr>
      <th colspan="3">
        <h4>守门员</h4>
      </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>td1</td>
      <td>td2</td>
      <td>td3</td>
    </tr>
    <tr>
      <td>td4</td>
      <td>td5</td>
      <td>td6</td>
    </tr>
  </tbody>
</table>

首先,您需要将项目分组为大小为 n(在您的情况下为3)的数组。您可以使用生成器函数:

function* toChunks(arr, n) {
  for (let i = 0; i < arr.length; i += n) {
    yield arr.slice(i, i + n);
  }
}
const rows = [...toChunks(items, 3)];

作为另一种选择,您也可以使用:

const chunk = (arr, n) =>
  [...Array.from({ length: Math.ceil(arr.length / n) }).keys()].map((key) =>
    arr.slice(key * n, (key + 1) * n)
  );
const rows = chunk(items, 3);

有了上述行,您的组件将如下所示:

const Goalies = ({ rows }) => (
  <tbody>
    {rows.map((row, rk) => (
      <tr key={rk}>
        {row.map((cell, ck) => (
          <td key={ck}>{cell.number}</td>
        ))}
      </tr>
    ))}
  </tbody>
);

演示链接

然而,根据您的数据,我认为您根本不应该在这里使用 table。您想要的布局可以更容易地通过以下方式实现:

const Cells = ({ items }) => (
  <div className="myWrapper">
    {items.map((item, key) => (
      <div key={key}>{item.number}</div>
    ))}
  </div>
)

以及以下CSS模型之一:

.myWrapper {
  display: flex;
  flex-wrap: wrap;
}
.myWrapper > * {
  width: calc(100%/3)
}

/* 或者替代方式: */
.myWrapper {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr))
}
英文:

In order to achieve the layout you're after, the correct HTML markup would look like this:

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th colspan=&quot;3&quot;&gt;
        &lt;h4&gt;Goalkeepers&lt;/h4&gt;
      &lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;td1&lt;/td&gt;
      &lt;td&gt;td2&lt;/td&gt;
      &lt;td&gt;td3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;td4&lt;/td&gt;
      &lt;td&gt;td5&lt;/td&gt;
      &lt;td&gt;td6&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

First, you'll want to group your items into arrays of n (3 in your case). I'd use a generator function:

function* toChunks(arr, n) {
  for (let i = 0; i &lt; arr.length; i += n) {
    yield arr.slice(i, i + n)
  }
}
const rows = [...toChunks(items, 3)]

As an alternative, you could also use:

const chunk = (arr, n) =&gt;
  [...Array.from({ length: Math.ceil(arr.length / n) }).keys()].map((key) =&gt;
    arr.slice(key * n, (key + 1) * n)
  )
const rows = chunk(items, 3)

Given the above rows, your component would look like this:

const Goalies = ({ rows }) =&gt; (
  &lt;tbody&gt;
    {rows.map((row, rk) =&gt; (
      &lt;tr key={rk}&gt;
        {row.map((cell, ck) =&gt; (
          &lt;td key={ck}&gt;{cell.number}&lt;/td&gt;
        ))}
      &lt;/tr&gt;
    ))}
  &lt;/tbody&gt;
)

Demo here


However, by looking at your data I think you shouldn't be using a &lt;table&gt; here at all. The layout you're after could easier be achieved with:

const Cells = ({ items }) =&gt; (
  &lt;div className=&quot;myWrapper&quot;&gt;
    {items.map((item, key) =&gt; (
      &lt;div key={key}&gt;{item.number}&lt;/div&gt;
    ))}
  &lt;/div&gt;
)

along with any of the following CSS models:

.myWrapper {
  display: flex;
  flex-wrap: wrap;
}
.myWrapper &gt; * {
  width: calc(100%/3)
}

/* or alternatively: */
.myWrapper {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr))
}

huangapple
  • 本文由 发表于 2023年2月10日 04:14:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75403964.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定