Search code examples
javascriptreactjsreact-dom

How to surround every X elements with a class using React.js


I'd simply like to do something as follows:

<div class="container">
  <div class="row">
    <div class="col-md-4">content</div>
    <div class="col-md-4">content</div>
    <div class="col-md-4">content</div>
  </div>
  <div class="row">
    <div class="col-md-4">content</div>
    <div class="col-md-4">content</div>
    <div class="col-md-4">content</div>
  </div>

   <!-- etc ... -->

</div>

Eg, every 3 .col-md-4's is wrapped in a .row

I've tried:

rows.push(<div className="row">);

   for (var count = 0; count < 9; count++) { 

       rows.push( <!-- content --> );

       // Add closing and reopening divs every 3 elements
       if (count % 3 === 0) {
          rows.push(</div><div className="row">);
       }
   }

   rows.push(</div>);
}

This unfortunately doesn't work.

Furthermore 3 and 9 are just examples here, and I was wondering if there was a generic approach.


Solution

  • You should not concatenate elements like a string, but create and compose react elements. You can generate an array of your elements with content first, then reduce it to groups and wrap with your container:

    render() {
        var content = [
            "content 1", "content 2", "content 3", "content 4", "content 5",
            "content 6", "content 7", "content 8", "content 9", "content 10"
        ];
        var groupSize = 3;
        var rows = content.map(function(content) {
            // map content to html elements
            return <div className="col-md-4">{content}</div>;
        }).reduce(function(r, element, index) {
            // create element groups with size 3, result looks like:
            // [[elem1, elem2, elem3], [elem4, elem5, elem6], ...]
            index % groupSize === 0 && r.push([]);
            r[r.length - 1].push(element);
            return r;
        }, []).map(function(rowContent) {
            // surround every group with 'row'
            return <div className="row">{rowContent}</div>;
        });
        return <div className="container">{rows}</div>;
    }