0

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?

Table-Sorting-Sandbox

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>
  );
}

Here is a photo of my output: Output

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

2

1 Answer 1

1

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:

Edit table-sorting-reactjs (forked)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.