0

Looping through a dozen items or more using map method in React app. Want 4 columns per row, so after col number 4, end row and create new row:

{index % 4===0 && </div><div className="row">}

But I can't do that because that's not valid JSX. I'm guessing there's a better way to do this.

Ricky
  • 1,587
  • 2
  • 12
  • 20

3 Answers3

1

Create an array of column elements, After every 4th element push the array into another array(rows array). Your final array would look like this.

[<tr>{[<td>1</td>, <td>2</td>, <td>3</td>, <td>4</td>]}</tr>];

You can directly render this array.

For ref - https://reactjs.org/docs/lists-and-keys.html

const Arr = [
  { name: "abc" },
  { name: "def" },
  { name: "ghi" },
  { name: "jkl" },
  { name: "mno" },
  { name: "pqr" }
];

function App() {
  const rows = [];
  let columns = [];
  Arr.forEach((data, index) => {
    if (index % 4 === 0) {
      rows.push(<tr>{columns}</tr>);
      columns = [];
    }
    columns.push(<td>{data.name}</td>);
  });

  // to push the remaining columns
  if(columns.length){
      rows.push(<tr>{columns}</tr>);
  }

  return <table>{rows}</table>;
}
Siddharth
  • 1,200
  • 8
  • 13
1

You can try this


const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
const componentArray = [];

export default function App() {
  const formComponents = () => {
    data.forEach((d, i) => {
      let index = Math.floor(i / 4);
      componentArray[index] = [
        ...(componentArray[index] || []),
        <span key={d}>{d}</span>
      ];
    });
    console.log(componentArray);
    return componentArray;
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      {/* <NewDevicePage /> */}
      {formComponents().map((comp, i) => (
        <div key={i}>{comp}</div>
      ))}
    </div>
  );
}


Hope this helps.

Nithish
  • 5,393
  • 2
  • 9
  • 24
1

Did something similar, but if you're just trying to control the number of columns for appearances, you can technically ignore this and just use CSS to display it the you want. Reference here: https://stackoverflow.com/a/45384426/11317072

Click "Run code snippet" to see it how it works.

// main.js

const App = () => {
  const myData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
  
  const retrievRowsByColNum = (data, colPerRow) => {
    const rows = [];
    let cols = [];
    for (let i = 0; i < data.length; i++) {
      cols.push(data[i]);
      if ((i + 1) % (colPerRow) === 0) {
        rows.push(cols);
        cols = [];
      }
    }
    if (cols && cols.length > 0) {
      rows.push(cols);
    }
    return rows;
  };
  
  return (<div>{(retrievRowsByColNum(myData, 4)).map((i, k) => i && i.length > 0 && <div key={`row-${k}`}>{i.map((c, ck) => <div key={`key-${ck}`}>col {c}</div>)}<br/></div>)}</div>);
}

ReactDOM.render(<App />, document.querySelector('#root'));
<body>
<div id="root"></div>

<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

<script type="text/babel" src="main.js"></script>
</body>
codingwithmanny
  • 1,126
  • 8
  • 20