Search code examples
reactjsreact-statereact-map-gl

React functional array delay to update


Helllo everyone, I have this issue where I am successfully sorting the array state of an object alphabetically using their cities but the problem is that the array that is getting visualized only updates after I search something on the UI.

I tried to look it up but still lost here is the video of what is happening https://drive.google.com/file/d/17pAwTeo8IZ6mw3dd2pxDxbfY-ToL7cjG/view?usp=sharing

here is the code

map where I visualize the list

sort function

full code here

import React, { useState, useEffect } from "react";
import "./body.css";
import Axios from "axios";
import { Button } from "@material-ui/core";

function SearchBar() {
  const [filteredData, setFilteredData] = useState([]);
  const [search, setSearch] = useState("");

  async function getUsers() {
    Axios.get("https://jsonplaceholder.typicode.com/users")
      .then((response) => {
        setFilteredData(response.data);
      })
      .catch((err) => {
        console.log(err);
      });
  }
  useEffect(() => {
    getUsers();
  }, []);

  function handleReset() {
    getUsers();

    setSearch("");
    handleClear();
  }

  const handleClear = () => {
    Array.from(document.querySelectorAll("input")).forEach(
      (input) => (input.value = "")
    );
  };

  const delItem = (id) => {
    setFilteredData(filteredData.filter((e) => e.name.localeCompare(id) !== 0));
  };

  const sort = () => {
    setFilteredData(
      filteredData.sort((a, b) => {
        return a.address.city.localeCompare(b.address.city);
      })
    );
    // console.log(sorted);
    // setFilteredData(sorted);
    console.log(filteredData);
  };

  return (
    <div>
      <form class="search-bar">
        <input
          type="input"
          name="search"
          pattern=".*\S.*"
          // requiredw
          autoComplete="off"
          placeholder="Input Text Here"
          onChange={(e) => setSearch(e.target.value)}
        ></input>
      </form>

      <Button onClick={handleReset}>Reset</Button>
      <Button onClick={sort}>Sort</Button>

      <div>
        <ul>
          {filteredData
            .filter((user) => {
              var dynamicSearch = search;

              if (
                user.name.toLowerCase().includes(dynamicSearch.toLowerCase()) ||
                user.email
                  .toLowerCase()
                  .includes(dynamicSearch.toLowerCase()) ||
                user.phone
                  .toLowerCase()
                  .includes(dynamicSearch.toLowerCase()) ||
                user.address.city
                  .toLowerCase()
                  .includes(dynamicSearch.toLowerCase())
              ) {
                return true;
              }
            })
            .map((val, index) => (
              <li className="li" key={val.id}>
                <p className="list">
                  {"Name: "}
                  {val.name} <br />
                  {"Email: "}
                  {val.email}
                  <br />
                  {"Phone: "}
                  {val.phone}
                  <br />
                  {"City: "}
                  {val.address.city}
                </p>
                <button className="delButton" onClick={() => delItem(val.name)}>
                  x
                </button>
              </li>
            ))}
        </ul>
      </div>
    </div>
  );
}

export default SearchBar;

Solution

  • Just try with this one:

      const sort = () => {
        const sortedData = filteredData.sort((a, b) => {
        return a.address.city.localeCompare(b.address.city);
        });
        setFilteredData([...sortedData]);
      };
    

    Problem is once you are updating the sorting data in setFilteredData function its not able to observe the changes that needs to be rendered. So always make the copy of the state variables when you are updating the values.