Skip to content

React JS sorting issue

I’m trying to sort some data in my application. I’d like to support the following options:

  • Price (low to high)
  • Price (high to low)
  • Mileage (low to high)
  • Mileage (high to low)

It looks like price sorting is working. However, when I click on “lowest mileage”, it keeps showing the highest price results – the old value of sorting. I tried useEffect, but I couldn’t make it work. Here’s my code:

App.js

      
      const [carList, setCarList] = useState(cars)
      const [sorting, setSorting] = useState("pricelow")
      
      const handleSort = (e) => {
        setSorting(e.target.value)
        if (sorting === "pricelow"){
          const newlist = carList.sort((a,b) => {
            return parseInt(b.carPrice) - parseInt(a.carPrice)
          })
          setCarList(newlist)
        }
        if (sorting === "pricehigh"){
          const newlist = carList.sort((a,b) => {
            return parseInt(a.carPrice) - parseInt(b.carPrice)
          })
          setCarList(newlist)
        }
        if (sorting === "kmlow"){
          const newlist = carList.sort((a,b) => {
            return parseInt(a.carMileage) - parseInt(b.carMileage)
          })
          setCarList(newlist)
        }
      }

AdsList.js

      <select className="form-select w-25" onChange={handleSort} value={sorting}>
          <option value="pricelow">Sort By Lowest Price</option>
          <option value="pricehigh">Sort By Highest Price</option>
          <option value="kmlow">Sort By Lowest Km</option>
          <option value="kmhigh">Sort By Highest Km</option>
      </select>

Answer

This is happening because the setSorting doesn’t change the sorting value straight away but rather waits until the component re-renders. See https://reactjs.org/docs/react-component.html#setstate

Do this instead:

 const [sorting, setSorting] = useState("pricelow")
  
  const handleSort = (e) => {
    const sortValue = e.target.value;
    setSorting(sortValue)
    
    if (sortValue === "pricelow"){
      const newlist = carList.sort((a,b) => {
        return parseInt(b.carPrice) - parseInt(a.carPrice)
      })
      setCarList(newlist)
    }
    if (sortValue === "pricehigh"){
      const newlist = carList.sort((a,b) => {
        return parseInt(a.carPrice) - parseInt(b.carPrice)
      })
      setCarList(newlist)
    }
    if (sortValue === "kmlow"){
      const newlist = carList.sort((a,b) => {
        return parseInt(a.carMileage) - parseInt(b.carMileage)
      })
      setCarList(newlist)
    }
  }

Another tip, use a switch/case for cleaner code.