Estoy tratando de hacer una tabla de usuarios ordenable que pueda ser ordenada por todos los encabezados de la tabla. He podido hacer que ordene de forma ascendente y descendente, pero solo por la columna de nombre. Soy nuevo en reactjs y no he podido implementarlo en mi código.
aquí está el componente de la tabla:
import { formatDate } from "../../utils/formatDate"; import "./table.css"; function Table(props) { const { headerData, bodyData, removeItem, sortData, ordIcon} = props; return ( <div className="user-data"> <table className="user-table"> <thead> <tr className="data-th"> {headerData.map((headerTable) => ( <th onClick={sortData} id={"header-"+headerTable.toLowerCase()}> {headerTable} <img src={ordIcon} id="arrow-img"></img> </th> ))} </tr> </thead> <tbody> {bodyData.map((item) => ( <tr className="data-tr"> <td>{item.name}</td> <td>{item.email}</td> <td>{item.occupation}</td> <td>{formatDate(item.birthday)}</td> </tr> ))} </tbody> </table> </div> ); } export default Table;y aquí está el código de clasificación en el Inicio:
const sortData = () => { if (order === "" || "asc") { let sortUserName = [...newUserArr].sort((a, b) => a.name.localeCompare(b.name) ); setOrder("dsc"); setNewUserArr(sortUserName); setOrdIcon(arrowDown) } if (order === "dsc") { let sortUserName = [...newUserArr].sort((a, b) => b.name.localeCompare(a.name) ); setOrder("asc"); setNewUserArr(sortUserName); setOrdIcon(arrowUp) } };Gracias
editar: headerData={headerUser}
const headerUser = ["Name", "Email", "Occupation", "Birthday"];
Aquí hay un enfoque genérico,
En el componente Home , agregue una variable que almacene la clave y el tipo de cada columna
const columnMap = { Name: {key: 'name', type: 'string'}, Email: {key: 'email', type: 'string'}, Occupation: {key: 'occupation', type: 'string'}, Birthday: {key: 'birthday', type: 'date'} }; Y luego, en el componente Table mientras se procesan los encabezados de las columnas, cambie onClick para que envíe la función columnHeader a sortData
{headerData.map((headerTable) => ( <th onClick={() => sortData(headerTable)} id={"header-"+headerTable.toLowerCase()}> {headerTable} <img src={ordIcon} id="arrow-img"></img> </th> ))} Y finalmente en la función sortData ,
const sortData = (columnHeader) => { const {key, type} = columnMap[columnHeader]; const sorted = [...newUserArr].sort((a, b) => { let sortValue = 0; if (type === 'date') { sortValue = new Date(a[key]) - new Date(b[key]); } else { sortValue = a[key].localeCompare(b[key]); } return order === 'dsc' ? -(sortValue) : sortValue; }); setNewUserArr(sorted); if (order === '' || 'asc') { setOrder('dsc'); setOrdIcon(arrowDown); } else { setOrder('asc'); setOrdIcon(arrowUp); } }; Primero encontramos la clave con la que necesitamos ordenar newUserArr , también necesitamos escribir aquí porque para las fechas no podemos usar localeCompare . Luego ordenamos la matriz, si el orden es dsc , invertimos la ordenación.
EDITAR: para los íconos de clasificación, podríamos realizar un seguimiento del estado de clasificación actual de cada columna y luego usarlo en el componente Table
En Home
const [sortStatus, setSortStatus] = useState({}); Y cambia sortData a
const sortData = (columnHeader) => { const {key, type} = columnMap[columnHeader]; const sorted = [...newUserArr].sort((a, b) => { let sortValue = 0; if (type === 'date') { sortValue = new Date(a[key]) - new Date(b[key]); } else { sortValue = a[key].localeCompare(b[key]); } return order === 'dsc' ? -(sortValue) : sortValue; }); setNewUserArr(sorted); setSortStatus((prev) => ({ ...prev, [columnHeader]: order === 'dsc' ? 'asc' : 'dsc' })) }; En el componente Table ,
const getSortIcon = (columnHeader) => { if (!sortStatus[columnHeader]) { return "↕︎"; } return sortStatus[columnHeader] === 'dsc' ? "↓" : "↑"; }; {headerData.map((headerTable) => ( <th onClick={sortData} id={"header-"+headerTable.toLowerCase()}> {headerTable} {getSortIcon(headerTable)} </th> ))}