Home > Net >  How to sort table by name?
How to sort table by name?

Time:10-15

I'm still a beginner in ReactJS and I'm doing a job where I need to sort my list of pokemons by name.

I'm using the Material-UI Table, but I can't do the ordering. Here's is my code I put into enter image description here

import React from "react";

import {
  Table,
  TableBody,
  TableContainer,
  TableHead,
  TableRow,
  TableCell
} from "@material-ui/core";

import { pokemons } from "./data";

import "./styles.css";

const App = () => {
  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]);
  }

  return (
    <TableContainer>
      <Table sx={{ maxWidth: 650 }}>
        <TableHead>
          <TableRow>
            <TableCell>Pokémon</TableCell>
            <TableCell align="right">Name</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {pokemons.map((pokemon) => (
            <TableRow
              key={pokemon.name}
              sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
            >
              <TableCell component="th" scope="row" thumbnailImage>
                <div className="thumb">
                  <img src={pokemon.thumbnailImage} alt="" />
                </div>
              </TableCell>
              <TableCell align="left" component="th" scope="row" description>
                {pokemon.name}
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

export default App;

Could you tell me what I'm doing wrong?

Thank you very much in advance.

CodePudding user response:

Hey i just made some improvements in your code. You can check it out now.

import React, { useState } from "react";

import {
  Table,
  TableBody,
  TableContainer,
  TableHead,
  TableRow,
  TableCell,
} from "@material-ui/core";

import { pokemons } from "./data";

import "./styles.css";

const App = () => {
  const [pokemonsState, setPokemonsState] = useState(pokemons);
  const [isAsecSort, setIsAsecSort] = useState(false);

  const onClickName = () => {
    if (isAsecSort)
      setPokemonsState(stableSort(pokemons, getComparator("aesc", "name")));
    else setPokemonsState(stableSort(pokemons, getComparator("desc", "name")));

    setIsAsecSort(!isAsecSort);
  };

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

  return (
    <TableContainer>
      <Table sx={{ maxWidth: 650 }}>
        <TableHead>
          <TableRow>
            <TableCell>Pokémon</TableCell>
            <TableCell align="right" onClick={() => onClickName()}>
              Name
            </TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {pokemonsState.map((pokemon, idx) => (
            <TableRow
              key={idx}
              sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
            >
              <TableCell component="th" scope="row">
                <div className="thumb">
                  <img src={pokemon.thumbnailImage} alt="" />
                </div>
              </TableCell>
              <TableCell align="left" component="th" scope="row">
                {pokemon.name}
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

export default App;

Things I changed -:

  1. Used the sorting function with 'name' as comprable.
  2. In pockemon mapping on DOM I used index as key because name was repeating.
  3. You used some weird fields (like thumbnailImage) in JSX element. So I removed them. Now it is completely error free.

Edit 1 -: To sort the array only after clicking name I added onClickListener on Name element (to make some hover effect you can use css or button/anchor tag). For automatic rerendering I used useState hook for storing pokemons instead of normal array.

Edit 2 -: To toggle the sort on each click I added a isAsecSort counter which will sort in ascending order if true else will sort in descending order.

  • Related