Reputation: 107
I try to make function that get an array of object and according to object in the array generate a table with dynamic rowspan. I tried many solutions but none of them helped.
I tried this code,but I did not continue it because the beginning did not work well
const returnTabel = state => {
return state.map((item, index) => {
return (
<tr key={index}>
{Object.keys(item).map((key, index) => {
if (Array.isArray(item[key])) {
return item[key].map((object, index) => {
return Object.keys(object).map((i, index) => {
if (Array.isArray(object[i])) {
} else {
return (
<tr>
<td>{object[i]}</td>
</tr>
);
}
});
});
} else {
return (
<td rowSpan={2} key={index}>
{item[key]}
</td>
);
}
})}
</tr>
);
});};
Here is my data:
const state = [
{
name: 'Bill',
info: [
{
hobby: 'Practice',
field: [
{ type: 'Swim', hours: '6' },
{ type: 'Run', hours: '7' }
]
},
{
hobby: 'Listen to music',
field: [
{ type: 'Jazz', hours: '3' },
{ type: 'Electronic music', hours: '3' },
{ type: 'Hip hop', hours: '3' }
]
}
],
student: 'No'
},
{
name: 'John',
info: [
{
hobby: 'Practice',
field: [
{ type: 'Swim', hours: '1' },
{ type: 'Run', hours: '2' }
]
}
],
student: 'Yes'
}]
I want to make this table with my data
Upvotes: 0
Views: 2154
Reputation: 171700
You can simplify the render mapping if you map the data to rows that look like:
[{"txt":"Bill","rowSpan":5},{"txt":"Practice","rowSpan":2},{"txt":"Swim"},{"txt":"6"},{"txt":"No","rowSpan":5}]
//OR
[null,{"txt":"Listen to music","rowSpan":3},{"txt":"Jazz"},{"txt":"3"},null]
//OR
[null,null,{"txt":"Run"},{"txt":"7"},null]
Then the render simplifies down to:
return (
<table border="1">
{rows.map(cells => (
<tr>
{cells.map(cell => cell && <td rowSpan={cell.rowSpan}>{cell.txt}</td>)}
</tr>
)
)}
</table>
);
Working example
const data=[{name:"Bill",info:[{hobby:"Practice",field:[{type:"Swim",hours:"6"},{type:"Run",hours:"7"}]},{hobby:"Listen to music",field:[{type:"Jazz",hours:"3"},{type:"Electronic music",hours:"3"},{type:"Hip hop",hours:"3"}]}],student:"No"},{name:"John",info:[{hobby:"Practice",field:[{type:"Swim",hours:"1"},{type:"Run",hours:"2"}]}],student:"Yes"}];
const rowData = data.reduce((a, { name, info, student }) => {
const rowSpan = info.reduce((a, { field }) => a + field.length, 0);
let [firstCell, lastCell] = [name, student].map(txt => ({ txt, rowSpan }));
info.forEach(({ hobby, field }, i) => {
const rowSpan = field.length;
let hobCell = { txt: hobby, rowSpan };
field.forEach((f, j) => {
const fieldCells = Object.values(f).map(txt => ({ txt }));
if (j > 0) {
hobCell = firstCell = lastCell = null;
}
const row = [firstCell, hobCell, ...fieldCells, lastCell];
a.push(row);
});
});
return a;
}, []);
console.log( rowData)
const Table = () => {
const [rows] = React.useState(rowData);
return (
<table border="1">
{rows.map((cells,i) => (
<tr key={i}>
{cells.map((cell,j) => cell && <td key={`${i}-${j}`} rowSpan={cell.rowSpan}>{cell.txt}</td>)}
</tr>
)
)}
</table>
);
};
// Render it
ReactDOM.render(
<Table />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Upvotes: 1