Home > Back-end >  sort table by click header in react
sort table by click header in react

Time:06-18

I have a table where I pass the DATA to it from a local JSON, I'm trying to make it update the values ​​when clicking on the header, in the log it works, what happens is that the event to change the items is not firing, I believe that because they are the same items...

see that my console log inside useEffect doesn't even fire...

import DATA from "./components/DB_DATA.json";

import "./App.css";
import { useState, useEffect } from "react";

import Table from "./components/Table";

function App() {
  const [data, setdata] = useState(DATA);

  useEffect(() => {
    console.log(data);
  }, [data]);

  function handleHeaderClick(header) {
    const newdata = data.sort((a, b) => (a[header] > b[header] ? 1 : -1));
    setdata(newdata);
  }

  return (
    <div>
      <Table data={data} onClick={handleHeaderClick} />
    </div>
  );
}

export default App;

@edit I added a console.log in newdata, to see if everything was right, and it's OK

enter image description here

@edit 2 insert Table component code

import "./table.css";

export default function Table(props) {
  function tableHeader(header, index) {
    if (header.includes("BET") || header.includes("Flop") || header.includes("CHECK")) {
      return (
        <th onClick={(e) => props.onClick(header)} key={index}>
          {header}
        </th>
      );
    }
  }

  function tableRow(row, indexRow) {
    return (
      <tr>
        {Object.keys(row).map((hd) => {
          if (hd.includes("BET") || hd.includes("Flop") || hd.includes("CHECK")) {
            return <td>{props.data[indexRow][hd]}</td>;
          }
        })}
      </tr>
    );
  }

  return (
    <table>
      <thead>{Object.keys(props.data[0]).map((header, indexHeader) => tableHeader(header, indexHeader))}</thead>
      <tbody>{props.data.map((row, indexRow) => tableRow(row, indexRow))}</tbody>
    </table>
  );
}

CodePudding user response:

Beware that Array.prototype.sort() mutates the array as well as returning the sorted array, so you need to copy it to a new array before sorting.

  function handleHeaderClick(header) {
    const newdata = [...data].sort((a, b) => (a[header] > b[header] ? 1 : -1));
    setdata(newdata);
  }

CodePudding user response:

You should try using this:

setdata(prevData => prevData.sort((a, b) => (a[header] > b[header] ? 1 : -1)));

This will ensure you are using most current version of the state. This is covered in the React Hooks docs.

CodePudding user response:

useEffect() will only work if the value of data is changed. Please check if the value which is passed to the handleHeaderClick(header) is changing after the click.

Sometimes you might have to create a new array as sort will not make a new array, it will only change the values in the array. Hence try to generate a new array by the spread (...) operator like:

[...data].sort(logic)

CodePudding user response:

It's hard to say anything specific when you can't really play around with the code. The one thing that might be wrong is that you are missing a "key"-prop on your tr-element. without a key-prop react cant distinguish different elements and doesn't know that it should re-render. I see that you have key-index on the th-element, but you should always use it when mapping over an array and rendering components, and they should always be unique.

  <tr>
        {Object.keys(row).map((hd, index) => {
          if (hd.includes("BET") || hd.includes("Flop") || hd.includes("CHECK")) {
            return <td key={`tr-${index`}>{props.data[indexRow][hd]}</td>;
          }
        })}
      </tr>
  • Related