Home > other >  React: Data.map not rerendering after data state has been updated
React: Data.map not rerendering after data state has been updated

Time:02-08

I am trying to learn how to sort some data using react and TailwindCss, but upon trying I found a problem which I can't put my finger on, after sorting the data array it's not data.map is not re-rendering and I don't know why, can someone help me understand how to fix it, and why this happens.

import { useState, useEffect } from "react";
import axios from "axios";

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

  // this is the sorting function
  const sortData = () => {
    setData(data.sort((a, b) => a.firstName.localeCompare(b.firstName)));
    console.log("sort",data);
  };

  useEffect(() => {
    axios
      .get("https://dummyapi.io/data/v1/user?limit=50", {
        headers: {
          "app-id": "6200ff0858dcad3e84d67c55",
        },
      })
      .then((res) => {
        setData(res.data.data);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

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

  return (
    <div className="flex justify-center min-h-screen App bg-background min-w-screen">
      <div className="container">
        <div className="flex flex-col items-center gap-4 py-5">
          <h1 className="text-3xl">Filter & sorting app</h1>
          <div className="relative w-full">
            <div className="right-0 ">
              <select className="flex content-end px-3 py-2 bg-white shadow-sm rounded-xl">
                <option
                  value="volvo"
                  className="text-gray-100"
                  selected
                  disabled
                  hidden
                >
                  Sort by
                </option>
                <option value="saab" onClick={sortData}>
                  Ascending
                </option>
                <option value="opel">Descending</option>
              </select>
            </div>
          </div>
          <div className="w-full flex justify-center gap-8 flex-wrap bg-white p-8 min-h-[300px] border-2 rounded-xl">
            {/* here i map on the data state but it does nor re-render after data has changed  */}
            {data?.length > 0 ? (
              data.map((user) => (
                <div
                  className="bg-blue-300 sm:w-[200px] sm:h-[200px] w-[150px] h-[150px] rounded-3xl p-4 flex flex-col items-center mt-8"
                  key={user.id}
                >
                  <img
                    src={user.picture}
                    alt={`"user_"${user.id}`}
                    className="relative w-20 h-20 rounded-full -top-12"
                  />
                  <div className="flex flex-row -mt-6 text-center sm:mt-0">
                    <h1 className="text-xl capitalize sm:text-3xl">
                      {user.title}.&nbsp;
                      <p className="text-sm sm:text-xl">
                        {user.firstName} {user.lastName}
                      </p>
                    </h1>
                  </div>
                </div>
              ))
            ) : (
              <div className="flex items-center justify-center">
                <h1 className="text-3xl">Loading...</h1>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

export default App;

EDIT: if you have a better implementation of this please let me know.

CodePudding user response:

This sort function does not return any array. so instead to this:

  const sortData = () => {
    setData(data.sort((a, b) => a.firstName.localeCompare(b.firstName)));
  };

Try this

  const sortData = () => { 
    var newArr = [...data];
    newArr.sort((a, b) => a.firstName.localeCompare(b.firstName))
    setData(newArr);
  };
  •  Tags:  
  • Related