Home > Software engineering >  Why sorting table does not work in react with useState?
Why sorting table does not work in react with useState?

Time:10-05

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

const App = () => {
  const [data, setData] = useState([
    {
      rank: 1,
      name: "John",
      age: 29,
      job: "Web developer",
    },
    {
      rank: 2,
      name: "Michael",
      age: 35,
      job: "Businessman",
    },
    {
      rank: 3,
      name: "Karl",
      age: 43,
      job: "Fashion Designer",
    },
    {
      rank: 4,
      name: "Adolf",
      age: 53,
      job: "Fashism",
    },
    {
      rank: 5,
      name: "Armen",
      age: 11,
      job: "Fortnite player",
    },
    {
      rank: 6,
      name: "Artak",
      age: 19,
      job: "Front-end developer",
    },
    {
      rank: 7,
      name: "Elon",
      age: 52,
      job: "Businessman",
    },
    {
      rank: 8,
      name: "Alik",
      age: 20,
      job: "Waiter",
    },
    {
      rank: 9,
      name: "Erik",
      age: 18,
      job: "Manager",
    },
    {
      rank: 10,
      name: "Sako",
      age: 50,
      job: "Economist",
    },
  ]);
  return (
    <div>
      <table style={{ margin: "3rem auto" }}>
        <thead>
          <tr>
            <th
              style={{ cursor: "pointer" }}
              onClick={() => {
                console.log(data);
                return setData((prev) => {
                  return prev.sort((a, b) => {
                    const aRank = a.rank;
                    const bRank = b.rank;
                    return bRank - aRank;
                  });
                });
              }}
            >
              Rank
            </th>
            <th>Name</th>
            <th>Age</th>
            <th>Job</th>
          </tr>
        </thead>
        <tbody>
          {data.map((item) => {
            return (
              <tr key={item.rank}>
                <td>{item.rank}</td>
                <td>{item.name}</td>
                <td>{item.age}</td>
                <td>{item.job}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

export default App;
I have correctly formatted all of my code! I was just mapping through data and whenever rank is clicked, it should sort text in a decreasing order and I am using useState, however the text in the table does not change, but bold data changes! bold. So I just dont understand the principle of working state, everything seems to be fine for me, if you help me I would be really grateful!

CodePudding user response:

The sort function sorts the array in place and returns a reference to the same array. So, as far as React is concerned, the state value is still pointing to the same array and hasn't changed. So there's no reason for it to re-render.

You can spread the resulting array values into a new array reference to tell React that it's a new array:

setData((prev) => [...prev.sort((a, b) => b.rank - a.rank)]);

(Also, you don't need to return the result of setData. Because it has no result, and a click handler doesn't do anything with a returned result.)

CodePudding user response:

You can make it work by returning a copy of the sorted array, and thus a different array from prev. Like so:

              onClick={() => {
                return setData((prev) => {
                  return [...prev.sort((a, b) => {
                    const aRank = a.rank;
                    const bRank = b.rank;
                    return bRank - aRank;
                  })];
                });
              }}

Here an example

CodePudding user response:

You can try this too.

setData([...data.sort((a, b) => a.rank - b.rank)]);
  • Related