Rendering and Grouping using React Tables

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

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:

  1. export class Roster extends React.Component{
  2. render(){
  3. return(
  4. <div id="tab">
  5. <table >
  6. <tbody>
  7. <tr>
  8. <td colSpan={3}>
  9. <h4>Goalkeepers</h4>
  10. </td>
  11. </tr>
  12. </tbody>
  13. <Goalies/>
  14. </table>
  15. </div>
  16. )
  17. }
  18. }

Component looping through object:

  1. class Goalies extends React.Component{
  2. getTable() {
  3. let td_array = [];
  4. let goal_object = {};
  5. Object.keys(goalies).forEach(function(key) {
  6. goal_object = (goalies[key]);
  7. });
  8. for(const checker in goal_object){
  9. td_array.push(<td key={checker}>{goal_object[checker].p_name} <br/> {goal_object[checker].city} <br/> {goal_object[checker].number}</td>);
  10. }
  11. return(
  12. <tr>
  13. {td_array}
  14. </tr>
  15. )
  16. }
  17. render() {
  18. return (<tbody>{this.getTable()}</tbody>)
  19. }
  20. }

Objects:

  1. export const def = {
  2. 1:{
  3. p_name:"p1",
  4. number: 2,
  5. city: "city1"
  6. },
  7. 2:{
  8. p_name:"p2",
  9. number: 5,
  10. city: "city2"
  11. },
  12. 3:{
  13. p_name:"p3",
  14. number: 3,
  15. city: "city3"
  16. },
  17. 4:{
  18. p_name:"p4",
  19. number: 7,
  20. city: "city4"
  21. },
  22. 5:{
  23. p_name:"p5",
  24. number: 15,
  25. city: "city5"
  26. },
  27. 6:{
  28. p_name:"p6",
  29. number: 21,
  30. city: "city6"
  31. }
  32. }

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{

  1. render(){
  2. return(
  3. &lt;div id=&quot;tab&quot;&gt;
  4. &lt;table &gt;
  5. &lt;tbody&gt;
  6. &lt;tr&gt;
  7. &lt;td colSpan={3}&gt;
  8. &lt;h4&gt;Goalkeepers&lt;/h4&gt;
  9. &lt;/td&gt;
  10. &lt;/tr&gt;
  11. &lt;/tbody&gt;
  12. &lt;Goalies/&gt;
  13. &lt;/div&gt;
  14. )
  15. }

}`

Component looping through object:

`class Goalies extends React.Component{

  1. getTable() {
  2. let td_array = [];
  3. let goal_object = {};
  4. Object.keys(goalies).forEach(function(key) {
  5. goal_object = (goalies[key]);
  6. });
  7. for(const checker in goal_object){
  8. 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;);
  9. }
  10. return(
  11. &lt;tr&gt;
  12. {td_array}
  13. &lt;/tr&gt;
  14. )
  15. }
  16. render() {
  17. return (&lt;tbody&gt;{this.getTable()}&lt;/tbody&gt;)
  18. }

}`

Objects:

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

  1. 2:{
  2. p_name:&quot;p2&quot;,
  3. number: 5,
  4. city: &quot;city2&quot;
  5. },
  6. 3:{
  7. p_name:&quot;p3&quot;,
  8. number: 3,
  9. city: &quot;city3&quot;
  10. },
  11. 4:{
  12. p_name:&quot;p4&quot;,
  13. number: 7,
  14. city: &quot;city4&quot;
  15. },
  16. 5:{
  17. p_name:&quot;p5&quot;,
  18. number: 15,
  19. city: &quot;city5&quot;
  20. },
  21. 6:{
  22. p_name:&quot;p6&quot;,
  23. number: 21,
  24. city: &quot;city6&quot;
  25. }

}

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标记如下所示:

  1. <table>
  2. <thead>
  3. <tr>
  4. <th colspan="3">
  5. <h4>守门员</h4>
  6. </th>
  7. </tr>
  8. </thead>
  9. <tbody>
  10. <tr>
  11. <td>td1</td>
  12. <td>td2</td>
  13. <td>td3</td>
  14. </tr>
  15. <tr>
  16. <td>td4</td>
  17. <td>td5</td>
  18. <td>td6</td>
  19. </tr>
  20. </tbody>
  21. </table>

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

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

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

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

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

  1. const Goalies = ({ rows }) => (
  2. <tbody>
  3. {rows.map((row, rk) => (
  4. <tr key={rk}>
  5. {row.map((cell, ck) => (
  6. <td key={ck}>{cell.number}</td>
  7. ))}
  8. </tr>
  9. ))}
  10. </tbody>
  11. );

演示链接

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

  1. const Cells = ({ items }) => (
  2. <div className="myWrapper">
  3. {items.map((item, key) => (
  4. <div key={key}>{item.number}</div>
  5. ))}
  6. </div>
  7. )

以及以下CSS模型之一:

  1. .myWrapper {
  2. display: flex;
  3. flex-wrap: wrap;
  4. }
  5. .myWrapper > * {
  6. width: calc(100%/3)
  7. }
  8. /* 或者替代方式: */
  9. .myWrapper {
  10. display: grid;
  11. grid-template-columns: repeat(3, minmax(0, 1fr))
  12. }
英文:

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

  1. &lt;table&gt;
  2. &lt;thead&gt;
  3. &lt;tr&gt;
  4. &lt;th colspan=&quot;3&quot;&gt;
  5. &lt;h4&gt;Goalkeepers&lt;/h4&gt;
  6. &lt;/th&gt;
  7. &lt;/tr&gt;
  8. &lt;/thead&gt;
  9. &lt;tbody&gt;
  10. &lt;tr&gt;
  11. &lt;td&gt;td1&lt;/td&gt;
  12. &lt;td&gt;td2&lt;/td&gt;
  13. &lt;td&gt;td3&lt;/td&gt;
  14. &lt;/tr&gt;
  15. &lt;tr&gt;
  16. &lt;td&gt;td4&lt;/td&gt;
  17. &lt;td&gt;td5&lt;/td&gt;
  18. &lt;td&gt;td6&lt;/td&gt;
  19. &lt;/tr&gt;
  20. &lt;/tbody&gt;
  21. &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:

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

As an alternative, you could also use:

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

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

  1. const Goalies = ({ rows }) =&gt; (
  2. &lt;tbody&gt;
  3. {rows.map((row, rk) =&gt; (
  4. &lt;tr key={rk}&gt;
  5. {row.map((cell, ck) =&gt; (
  6. &lt;td key={ck}&gt;{cell.number}&lt;/td&gt;
  7. ))}
  8. &lt;/tr&gt;
  9. ))}
  10. &lt;/tbody&gt;
  11. )

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:

  1. const Cells = ({ items }) =&gt; (
  2. &lt;div className=&quot;myWrapper&quot;&gt;
  3. {items.map((item, key) =&gt; (
  4. &lt;div key={key}&gt;{item.number}&lt;/div&gt;
  5. ))}
  6. &lt;/div&gt;
  7. )

along with any of the following CSS models:

  1. .myWrapper {
  2. display: flex;
  3. flex-wrap: wrap;
  4. }
  5. .myWrapper &gt; * {
  6. width: calc(100%/3)
  7. }
  8. /* or alternatively: */
  9. .myWrapper {
  10. display: grid;
  11. grid-template-columns: repeat(3, minmax(0, 1fr))
  12. }

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:

确定