I'm currently trying to improve my skills in using JavasScript, React and Material-UI. I'm trying to sort my table using a nested JSON and I'm stuck with assigning my JSON fields to my array. Is there any way I can access and assign my JSON to the id in my array?
Here is the copy of my JSON:
{
"data": {
"transactions": [
{
"referenceNumber": "912349949908",
"transaction": "Reload",
"details": {
"sourceAccntNickname": "1jkp",
"sourceAcountNumber": "6*****48",
"transactionDate": "Feb 08, 2018",
"billerName": "Bill1",
"billerAccntNumber": "6***98",
"recurring": false,
"amount": 100000
},
"status": "failed"
},
{
"referenceNumber": "01237659123",
"transaction": "Reload",
"details": {
"sourceAccntNickname": "4jkp",
"sourceAcountNumber": "7*****48",
"transactionDate": "Feb 11, 2018",
"billerName": "Bill4",
"billerAccntNumber": "6***98",
"recurring": true,
"frequency": "Monthly",
"amount": 400000
},
"status": "success"
},
{
"referenceNumber": "012836591828",
"transaction": "Reload",
"details": {
"sourceAccntNickname": "3jkp",
"sourceAcountNumber": "7*****48",
"transactionDate": "Feb 10, 2018",
"billerName": "Bill3",
"billerAccntNumber": "6***98",
"recurring": true,
"frequency": "Monthly",
"amount": 300000
},
"status": "pending"
},
{
"referenceNumber": "69880129365123",
"transaction": "Reload",
"details": {
"sourceAccntNickname": "2jkp",
"sourceAcountNumber": "7*****48",
"transactionDate": "Feb 09, 2018",
"billerName": "Bill2",
"billerAccntNumber": "6***98",
"recurring": true,
"frequency": "Monthly",
"amount": 200000
},
"status": "failed"
}
]
}
}
Here is the source code for my table head array that needs sorting:
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
return -1;
}
if (b[orderBy] > a[orderBy]) {
return 1;
}
return 0;
}
function getComparator(order, orderBy) {
return order === 'desc'
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy);
}
function stableSort(array, comparator) {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) return order;
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
/* const date = SchedData.data.transactions.map(
(data) => data.details.transactionDate
);
console.log('Dates:', date, typeof date); */
const headCells = [
{
id: 'transactionDate',
numeric: false,
disablePadding: true,
label: 'PAYMENT DATE',
},
{ id: 'recurring', numeric: false, disablePadding: false, label: 'SCHEDULE' },
{ id: 'frequency', numeric: false, disablePadding: false, label: 'BILLER' },
{
id: 'sourceAccntNickname',
numeric: false,
disablePadding: false,
label: 'SOURCE',
},
{ id: 'amount', numeric: true, disablePadding: false, label: 'AMOUNT' },
{ id: 'status', numeric: false, disablePadding: false, label: 'STATUS' },
];
const StyledTableCell = withStyles((theme) => ({
head: {
backgroundColor: theme.palette.action.hover,
},
body: {
fontSize: 14,
},
}))(TableCell);
function EnhancedTableHead(props) {
const {
classes,
onSelectAllClick,
order,
orderBy,
numSelected,
rowCount,
onRequestSort,
} = props;
const createSortHandler = (property) => (event) => {
onRequestSort(event, property);
};
return (
<TableHead>
<TableRow>
{headCells.map((headCell) => (
<StyledTableCell
key={headCell.id}
sortDirection={orderBy === headCell.id ? order : false}
>
<TableSortLabel
active={orderBy === headCell.id}
direction={orderBy === headCell.id ? order : 'asc'}
onClick={createSortHandler(headCell.id)}
>
{headCell.label}
{orderBy === headCell.id ? (
<span className={classes.visuallyHidden}>
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
</span>
) : null}
</TableSortLabel>
</StyledTableCell>
))}
</TableRow>
</TableHead>
);
}
Assigning a field that isn't nested like the status field works but what can I do if it's inside a nest? I tried everything I could think of but I think I now need help from you guys. And any help, tips, recommendations etc will be so much appreciated. Thank you!
EDIT(8/16/20): HI: Here is a link for a sandbox copy of my work: Table-Sorting-Sandbox
One possible solution you might want to consider is to flatten your data first — remove the nesting.
You can use useEffect
to prepare your data before the table renders. Check the code below.
export default function Scheduled() {
const classes = useStyles();
const [order, setOrder] = React.useState("asc");
const [orderBy, setOrderBy] = React.useState("");
// state that will hold the flattened data
const [schedData, setSchedData] = React.useState([]);
React.useEffect(() => {
const { transactions } = SchedData.data;
const schedData = transactions.map((transaction) => {
// make all `details` properties to be accessible
// on the same level as `status`
return { ...transaction, ...transaction.details };
});
setSchedData(schedData);
}, []);
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === "asc";
setOrder(isAsc ? "desc" : "asc");
setOrderBy(property);
};
return (
<div className={classes.root}>
<Paper className={classes.paper}>
<TableContainer>
<Table
className={classes.table}
aria-labelledby="tableTitle"
aria-label="enhanced table"
>
<EnhancedTableHead
classes={classes}
order={order}
orderBy={orderBy}
onRequestSort={handleRequestSort}
rowCount={schedData}
/>
<TableBody>
{stableSort(schedData, getComparator(order, orderBy)).map(
(data, index) => {
return (
<TableRow tabIndex={-1} key={index}>
{/* notice here, we don't have to use `data.details` */}
<TableCell>{data.transactionDate}</TableCell>
<TableCell>{data.frequency}</TableCell>
<TableCell>{data.billerName}</TableCell>
<TableCell>{data.sourceAccntNickname}</TableCell>
<TableCell>{data.amount}</TableCell>
<Table>{data.status}</Table>
</TableRow>
);
}
)}
</TableBody>
</Table>
</TableContainer>
</Paper>
</div>
);
}
Forked and updated codesandbox:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.