I\'m using react
and I want to render
a new row every 4th column.
My code:
function Product(props) {
const content = prop
You can do something like this:
render() {
function toChunkArray(myArray: any, chunkSize: any): any {
var results = [];
while (myArray.length) {
results.push(myArray.splice(0, chunkSize));
}
return results;
}
let chunkedArraysOfColSize = toChunkArray(myList, 3);
return (
<div className="row">
{
chunkedArraysOfColSize.map( (colSizeArray, index) =>
<div className="col-sm-4" key={index.toString()}>
{colSizeArray.map((o, i) =>
<NameOfComponent key={o.Id} obj={o} />
)}
</div>
)
}
</div>
);
}
You want to wrap new row for each 4 columns, right?
Try this
render() {
const products = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let rowContents = [];
const contents = products.reduce((acc, p, i) => {
rowContents.push(<div key={i} className="col col-md-3">Col {p}</div>);
if (i % 4 === 3) {
acc.push(<div className="row">{rowContents}</div>);
rowContents = [];
}
return acc;
},[])
contents.push(<div className="row">{rowContents}</div>);
return (
<div>
{contents}
</div>
)
}
You can have a single row and all columns (col-md-3) can go inside that. To achieve multiple row effect after each 4th column, you can set style to every 4th column like this-
<div className="col-md-3" style={{clear: (index != 0 && index % 4 == 0) ? 'both' : 'none'}}></div>
This will achieve the same result as having multiple rows.
write it like this:
function Product(props) {
let content = [];
props.products.forEach((product, i) =>{
if((i+1) % 4 == 0){
content.push(
<div className="row" key={product.id}>
<article key={product.id} className="col-md-3"></article>
</div>
)
}else{
content.push(<article key={product.id} className="col-md-3"></article>);
}
});
return (
<div>
{content}
</div>
);
}
The nice thing about Bootstrap is that you can keep all the col*
in a single row
, and then insert a full-width div
every 4 columns to force the wrap. These keeps it simpler and you don't have to chunk the data.
Here's what the React render looks like:
render() {
let columns=[];
this.props.items.forEach((item,idx) => {
// push column
columns.push(
<div className="col-sm py-3" key={idx}>
Content
</div>
)
// force wrap to next row every 4 columns
if ((idx+1)%4===0) {columns.push(<div className="w-100"></div>)}
})
return (
<div className="row">
{columns}
</div>
)
}
Demo: https://www.codeply.com/go/VMV26jhHFz
Note: In Bootstrap 4, use <div className="w-100"></div>
as shown above. In Bootstrap 3, use <div className="clearfix"></div>
to force the columns to wrap every n.
Group your products into rows of (at most) 4 elements, i.e.
[1,2,3,4,5,6,7,8] => [ [1, 2, 3, 4], [5, 6, 7, 8 ] ]
Iterate over the groups to generate rows, and in an inner loop iterate over the items to display columns
To calculate the number of rows, given 4 items per row, use Math.ceil(props.products.length / 4)
. Then create an array of rows. Given 2 rows (for 8 items): Array(2)
. Since you can't map
an array of uninitialized elements, you can use spread syntax: [...Array(2)]
which returns [ undefined, undefined ]
.
Now you can map these undefined
entries into rows: for each row take 4 elements from products: [ undefined, undefined ].map( (row, idx) => props.products.slice(idx * 4, idx * 4 + 4) ) )
(edit note changed to slice
since splice
mutates the original array). The result is an array of arrays (rows of items).
You can iterate over the rows, and inside each iteration iterate over the items in given row.
https://jsfiddle.net/dya52m8y/2/
const Products = (props) => {
// array of N elements, where N is the number of rows needed
const rows = [...Array( Math.ceil(props.products.length / 4) )];
// chunk the products into the array of rows
const productRows = rows.map( (row, idx) => props.products.slice(idx * 4, idx * 4 + 4) ); );
// map the rows as div.row
const content = productRows.map((row, idx) => (
<div className="row" key={idx}>
// map products in the row as article.col-md-3
{ row.map( product => <article key={product} className="col-md-3">{ product }</article> )}
</div> )
);
return (
<div>
{content}
</div>
);
}