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
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 -:
- Used the sorting function with 'name' as comprable.
- In pockemon mapping on DOM I used index as key because name was repeating.
- 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.