Why is array not updating after sorting in React Hooks?

Viewed 3684

I am new to React. The array in state is updating only once after sort function. Why is it not updated again after the sort function is triggered second time?

const [cases, setCases] = useState([1, 2, 3, 4, 5]);

let sortDown = true
let sorted = []

    function sort(){
        const copy = [...cases]
        if(sortDown){
            sorted = copy.sort(function(a, b){
                return b - a 
            })
        } else {
            sorted = copy.sort(function(a, b){
                return a - b
            })
        }
        sortDown = !sortDown
        setCases(sorted)
    }

2 Answers

React rerenders the component when props or state changed. In your case, you declare sorted array and then you pass it to setCases. So for the first time setCases takes sorted array and it is new value for that. Then you sort the values again and you mutate the sorted array and pass it again to setCases. But setCases doesn't consider sorted as a new array because it was mutated so the reference was not changed. For React it is still the same array you passed at first time. You need to return new array and then pass it to setCases.

The other thing you should do is to store sortDown in state. Otherwise it will be reintialized every render. Following code should work in your case:

    const [cases, setCases] = useState([1, 2, 3, 4, 5]);
    const [sortDown, setSortDown] = useState(true)

        function sort(){
            const copy = [...cases] // create copy of cases array (new array is created each time function is called)
            if(sortDown){
                copy.sort(function(a, b){ // mutate copy array
                    return b - a 
                })
            } else {
                copy.sort(function(a, b){
                    return a - b
                })
            }
            setSortDown(!sortDown); // set new value for sortDown
            setCases(copy); // pass array to setCases
        }

You should be using a state variable to decide sortType.

otherwise it'll be reinitialized every render.

  const [cases, setCases] = useState([1, 2, 3, 4, 5]);
  const [sortDown, setSortDown] = useState(true);

  function sort() {
    const copy = [...cases];
    if (sortDown) {
      copy.sort(function(a, b) {
        return b - a;
      });
    } else {
      copy.sort(function(a, b) {
        return a - b;
      });
    }
    setSortDown((prev) => !prev);
    setCases(copy);
  }
Related