1

Given an even length array, I am trying to find a clean method using React to put half an array in one div tag and inside it, each element should be in a span tag, and the same for the other half. For example, given the array of numbers 1 to 6, the rendered output should be:

<div>
    <span>1</span>
    <span>2</span>
    <span>3</span>
</div>
<div>
    <span>4</span>
    <span>5</span>
    <span>6</span>
</div>

The main problem is dealing with the JSX combined with the JS, I can't figure how to achieve this result since some inner loop seems to must be used and it interferes with the returned rendered JSX.

I will also need this to be extended to do similar functionality with splitting the array to different amount of <div> tags, e.g. 3 <div> tags with 2 <span> tags in each.

How can we achieve this in a clean manner?

namgold
  • 1,009
  • 1
  • 11
  • 32
user10364768
  • 135
  • 5
  • 1
    have a look here https://stackoverflow.com/questions/8495687/split-array-into-chunks for chunking your array of data into smaller chunks, and use a nested map to render your chunks. If is specifically half the array each time, you could use array slice using half the length of the array. It would also be good to see what you have tried specifically – andy mccullough Dec 23 '20 at 13:27
  • If this is a layout issue, maybe look into using CSS Grids instead so you don't need to manually split things into divs. – AKX Dec 23 '20 at 13:37

3 Answers3

1

You can do it like this:

const arr = [1, 2, 3, 4, 5, 6];
.....

// Inside some JSX components render method
{[arr.slice(0, arr.length / equalParts),
  arr.slice(arr.length / equalParts - 1, arr.length)].map(
  (half, index) => (
    <div key={`outer_${index}`}>
      {half.map((item, index) => (
        <span key={`inner_${index}`}>{item}</span>
      ))}
    </div>
  ),
)}

For the second part of the question you can extract it to a function:

const splitAndRender = (arr: number[], equalParts: number) => {
  const slices = [];

  const innerLength = arr.length / equalParts;

  for (let i = 0; i < equalParts; i++) {
    slices.push(arr.slice(i * innerLength, (i + 1) * innerLength));
  }

  return slices.map((half, index) => (
    <div key={`outer_${index}`}>
      {half.map((item, index) => (
        <span key={`inner_${index}`}>{item}</span>
      ))}
    </div>
  ));
};

and use the function like:

const arr = [1, 2, 3, 4, 5, 6];
.....

{splitAndRender(arr, 3)}
Lazar
  • 627
  • 1
  • 5
  • 17
  • 1
    `arr.splice()` modifies `arr` – it doesn't sound like something you'd want to use in a render method. – AKX Dec 23 '20 at 13:38
1

You can use _.chunk() of lodash to split array:

const array = [1, 2, 3, 4, 5, 6];
const n=2;

render() {
    return _.chunk(array, [size=n]).map(subArray => <div>{subArray.map(i => <span>i</span>}</div>);
}
namgold
  • 1,009
  • 1
  • 11
  • 32
1

in React needs to close tags inline so i found just this (not so performant) way:

const TMP = ({data,splitby}) => {
  let transformedData = data.reduce((r,v,i)=>{
    if (i%splitby)
      r[r.length-1].push(v)
    else r.push([v]);
    return r
  },[])

  return <div>
     {
       transformedData.map((v,index)=>(
         <div key={`div-$index`}>
           {
             v.map((s,idx)=> <span key={`div-${index}-span-${idx}`}>{s}</span>)
           }
         </div>
        ))
     }
  </div>
};

ReactDOM.render(
  <TMP data={Array.from({length: 25}, (v, i) => i)} splitby={3}/>,
  document.getElementById("tmp_root")
);
div {
  border: 1px solid tomato;
}

span {
  display: block;
  border:1px solid silver;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


<div id="tmp_root"></div>
Vahid Alimohamadi
  • 4,900
  • 2
  • 22
  • 37