Maison > Questions et réponses > le corps du texte
Mon code ci-dessous s'exécute mais j'obtiens une erreur "trop de rendus". Je ne sais pas pourquoi. Si je retire le double commutateur et que je le base sur une unité (comme le prix), cela fonctionne. Cependant, je ne trouve pas où mon code provoque la boucle infinie. Internet indique que j'utilise peut-être incorrectement useState. Toute aide est appréciée. Je suis un débutant, alors comprenez que j'ai peut-être fait quelque chose de stupide ! Quoi qu’il en soit, apprendre, c’est bien ! Merci.
import React from "react"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableCell from "@mui/material/TableCell"; import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; import Paper from "@mui/material/Paper"; import TableSortLabel from "@mui/material/TableSortLabel"; import { useState } from "react"; function createData(number, item, qty, price) { return { number, item, qty, price }; } const rows = [ createData(1, "Apple", 5, 3), createData(2, "Orange", 2, 2), createData(3, "Grapes", 3, 1), createData(4, "Tomato", 2, 1.6), createData(5, "Mango", 1.5, 4) ]; export default function SortedTable() { const [rowData, setRowData] = useState(rows); const [orderDirection, setOrderDirection] = useState("asc"); const [orderUnit, setOrderUnit] = useState("number"); const sortArray = (arr, orderBy, orderUn) => { switch (orderUn) { case "number": default: switch (orderBy) { case "asc": default: return arr.sort((a, b) => a.number > b.number ? 1 : b.number > a.number ? -1 : 0 ); case "desc": return arr.sort((a, b) => a.number > b.number ? 1 : b.number > a.number ? -1 : 0 ); } case "item": switch (orderBy) { case "asc": default: return arr.sort((a, b) => a.item > b.item ? 1 : b.item > a.item ? -1 : 0 ); case "desc": return arr.sort((a, b) => a.item < b.item ? 1 : b.item < a.item ? -1 : 0 ); } case "qty": switch (orderBy) { case "asc": default: return arr.sort((a, b) => a.qty > b.qty ? 1 : b.qty > a.qty ? -1 : 0 ); case "desc": return arr.sort((a, b) => a.qty < b.qty ? 1 : b.qty < a.qty ? -1 : 0 ); } case "price": switch (orderBy) { case "asc": default: return arr.sort((a, b) => a.price > b.price ? 1 : b.price > a.price ? -1 : 0 ); case "desc": return arr.sort((a, b) => a.price < b.price ? 1 : b.price < a.price ? -1 : 0 ); } } }; const handleSortRequest = (unit) => { setOrderUnit(orderUnit === unit); setRowData(sortArray(rows, orderDirection, orderUnit)); setOrderDirection(orderDirection === "asc" ? "desc" : "asc"); }; return ( <TableContainer component={Paper}> <Table aria-label="simple table" > <TableHead> <TableRow> <TableCell align="center" onClick={handleSortRequest("number")}><TableSortLabel active={true} direction={orderDirection}> S.No </TableSortLabel></TableCell> <TableCell align="center" onClick={handleSortRequest("item")}><TableSortLabel active={true} direction={orderDirection}> Item </TableSortLabel></TableCell> <TableCell align="center" onClick={handleSortRequest("qty")}><TableSortLabel active={true} direction={orderDirection}> Quantity (kg) </TableSortLabel></TableCell> <TableCell align="center" onClick={handleSortRequest("price")}> <TableSortLabel active={true} direction={orderDirection}> Price ($) </TableSortLabel> </TableCell> </TableRow> </TableHead> <TableBody> {rowData.map((row) => ( <TableRow key={row.number}> <TableCell width="100" component="td" scope="row" align="center"> {row.number} </TableCell> <TableCell align="center">{row.item}</TableCell> <TableCell align="center">{row.qty}</TableCell> <TableCell align="center">{row.price}</TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> ); }
J'essaie de rendre chaque colonne triable en fonction de la colonne cliquée. Question bonus, pourquoi mes en-têtes ne correspondent-ils pas aux colonnes ci-dessous lors du rendu.
P粉8019040892023-09-15 11:54:02
Vous devez transmettre la référence de la fonction au lieu d'appeler la fonction directement. De cette façon, la fonction ne sera appelée que lorsque l'événement se produit, plutôt qu'immédiatement lors du rendu du composant.
onClick={() => handleSortRequest("item")}
J'ai également refactorisé votre fonction sortArray pour la rendre lisible. Si c'est faux. S'il vous plaît, ne le dérangez pas. :D
const sortArray = useCallback((arr, orderBy, orderUn) => { const compare = (a, b, prop, order) => { if (order === "asc") { return a[prop] > b[prop] ? 1 : b[prop] > a[prop] ? -1 : 0; } else { return a[prop] < b[prop] ? 1 : b[prop] < a[prop] ? -1 : 0; } }; switch (orderUn) { case "number": default: return arr.sort((a, b) => compare(a, b, "number", orderBy)); case "item": return arr.sort((a, b) => compare(a, b, "item", orderBy)); case "qty": return arr.sort((a, b) => compare(a, b, "qty", orderBy)); case "price": return arr.sort((a, b) => compare(a, b, "price", orderBy)); } }, []);
Utilisez useCallback pour éviter un nouveau rendu inutile lorsque les dépendances n'ont pas changé
const handleSortRequest = useCallback( (unit) => { setOrderUnit(orderUnit === unit); setRowData(sortArray(rows, orderDirection, orderUnit)); setOrderDirection(orderDirection === "asc" ? "desc" : "asc"); }, [orderDirection, orderUnit, sortArray] );
J'espère que cela vous sera utile.