AFAIK you can't conditionally render opening/closing tags within array::map in react, each element mapped in JSX needs to be a complete node.
You can achieve the grouping by first splitting your array into an array of chunks, then map both the outer array of chunks and the inner chunk arrays.
Splitting an array into length-3 chunks there is this solution (closed but points here), though this would require some "pre-processing" before rendering.
Given some data array [0..15]
const data = [...Array(16).keys()];
You could copy into a temp array and splice off chunks of 3 elements
const data2 = [...data];
const groupedData1 = [];
while(data2.length) {
groupedData1.push(data2.splice(0, 3));
}
const data = [...Array(16).keys()];
const data2 = [...data];
const groupedData1 = [];
while(data2.length) {
groupedData1.push(data2.splice(0, 3));
}
console.log(groupedData1);
If you prefer the more functional, in-line approach commonly used in JSX. Here an array::reduce is used to reduce the data array into chunks of 3, and the final array::filter is used to clear out any ending empty array (as is the case when the chunk length divides the data length.
const groupedData2 = data
.reduce((groups, curr) => {
const arr = groups[groups.length - 1];
arr.push(curr);
if (arr.length === 3) groups.push([]);
return groups;
}, [[]])
.filter((chunk) => chunk.length);
const data = [...Array(16).keys()];
const groupedData2 = data
.reduce((groups, curr) => {
const arr = groups[groups.length - 1];
arr.push(curr);
if (arr.length === 3) groups.push([]);
return groups;
}, [[]])
.filter((chunk) => chunk.length);
console.log(groupedData2);
Now to render the chunked arrays
data.<inlineChunkProcess>.map((group, i) => (
<div key={i}>
{group.map((product, i) => (
<Product key={i} value={product} />
))}
</div>
))
This is a high-level overview, in actuality you'll not want to use the array index as a react key. When chunking/grouping your data you'll want to generate a unique id for that group and you'll want each product to have its own unique id (which hopefully is already the case). This will help if/when you need to add or remove any single product from your list.
Example:
const Group = () => ({
id: uuidv4(),
data: []
});
...
{list
.reduce(
(groups, curr) => {
const group = groups[groups.length - 1];
group.data.push(curr);
if (group.data.length === 3) {
groups.push(new Group());
}
return groups;
},
[new Group()]
)
.filter(({ data }) => data.length)
.map(({ data, id }, i) => (
<div key={id} className="myDiv">
Group Id: {id}
<div>
{data.map(({ id, value }, i) => (
<Product key={id} value={value} />
))}
</div>
</div>
))}
