'React setState array not getting sorted

My code is this:

handleFavourite = id => {
    const { restaurants } = this.state;
    let newRestaurants = [...restaurants];
    newRestaurants = sort(newRestaurants, 'favourite');
    console.log(newRestaurants); // ALL GOOD
    this.setState({ restaurants: newRestaurants }, () => console.log(this.state.restaurants)); // CONSOLE LOG POSTS OLD DATA
};

So there. The callback function in setState shows old data and in UI nothing gets sorted as well. Why is it that way?

edit: Found the problem. I'm also using static getDerivedStateFromProps and it's resetting the state every time.



Solution 1:[1]

handleFavourite seems to work a O.K.

class App extends React.Component {
  state = {
    restaurants: ["a", "b", "c"]
  }
  
  handleFavourite = id => {
    const { restaurants } = this.state;
    let newRestaurants = [...restaurants];
    newRestaurants = sort(newRestaurants, 'favourite');
    console.log(newRestaurants); // ALL GOOD
    this.setState({ restaurants: newRestaurants }, () => console.log(this.state.restaurants)); // CONSOLE LOG POSTS OLD DATA
}

render() {
  const restaurants = this.state.restaurants.map(r => <p>{r}</p>)
  return (
    <div>
      {restaurants}
    <hr/>
    <button onClick={this.handleFavourite}>sort</button>
    </div>
  )
}
}

function sort(r) {
  return r.reverse();
}

ReactDOM.render(<App/>, document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Solution 2:[2]

 newRestaurants = sort(newRestaurants, 'favourite'); 
// This mutates the original array and does not create a new copy.

A workaround is to create a new copy using slice function
    newRestaurants = sort(newRestaurants, 'favourite').slice(); 
    this.setState({ restaurants: newRestaurants });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 marzelin
Solution 2