React toggle for sorting doesn't work. Individual functions work

Viewed 122

I created two buttons for sorting the year field of a list ascending and descending. They work perfectly. And then I want to replace the buttons with one toggle button to change between ascending and descending. It doesn't work. My codes below. Would someone please advise? Thank you very much.

import { useEffect, useState } from 'react';
import {Button} from "reactstrap";

const MovieList = () => {    

  const [movies, setMovies] = useState([])
  const [sort, setSort] = useState(true)

    // Sort by Year
    // I need to use localeCompare because the year is string
  const sortByYearDesc = () => {
    const sorted = [...movies].sort((a, b) => {
      return b.year.localeCompare(a.year);
    });
    setMovies(sorted);
  }
  
  const sortByYearAsc = () => {
    const sorted = [...movies].sort((a, b) => {
      return a.year.localeCompare(b.year);
    });
    setMovies(sorted);
  }

  const toggleSort = () => {
    setSort(!sort)
    return sort ? sortByYearAsc  :  sortByYearDesc

  }

    return (
      
    <div className="container">
      <h1>Movies</h1>
        <hr />
        <div>
          <Button onClick={toggleSort} color="info">{sort ? "Sort by Desc" : "Sort by Asc"}</Button>
        </div>
            
      <div>
        <table className="table table-bordered table-striped">
          <thead className="thead-dark">
            <tr>
              <th>Year</th>
              <th>Film Name</th>
              <th>Oscar Winner</th>
              <th>Country</th>
            </tr>
          </thead>
          <tbody>
                {movies.map(movie => (
                <tr key={movie.id}>
                <td>{movie.year}</td>
                <td>{movie.filmName}</td>
                <td>{movie.winner}</td>
                <td>{movie.country}</td>
            </tr>
            ))}
          </tbody>
          </table>
          
      </div>
    </div>
    )
}

export default MovieList;
1 Answers

Since sortByYearAsc and sortByYearDesc are functions, you need to execute them in the toggleSort function.

e.g. the updated code will be

const toggleSort = () => {
  setSort(prevSort => !prevSort)
  !sort ? sortByYearAsc()  :  sortByYearDesc() // since the state is not updated yet.
}

Option 2

You can also use the useEffect hook, whenever the sort updates, that useEffect will execute the relevant function.

Only update the state in toggleSort

const toggleSort = () => {
  setSort(prevSort => !prevSort)
}

then use the useEffect based on the sort changes

useEffect(() => {
  sort ? sortByYearAsc()  :  sortByYearDesc()
}, [sort])
Related