7

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)
    }

3
  • 4
    Please show your full code, with the calls to sort() Commented Apr 10, 2020 at 12:03
  • 1
    Sort directly manipulate the array. You don't need to keep the sorted array into a new array. the copy array is sorted. So use setCases(copy) instead. Commented Apr 10, 2020 at 12:04
  • 1
    No one can't answer "why the sort is triggered twice" without showing how you call this function. Commented Apr 10, 2020 at 12:14

2 Answers 2

14

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
        }
Sign up to request clarification or add additional context in comments.

1 Comment

setSortDown(!sortDown); - avoid this
5

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);
  }

3 Comments

What changes did you make? Please explain your answer
sortDown is state variable now.
Sorting can be made simpler when you use direction that can either be 1 or -1: [...cases].sort((a, b) => (a - b) * direction)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.