Xeen
Xeen

Reputation: 7003

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.

Upvotes: 2

Views: 2918

Answers (3)

anand k
anand k

Reputation: 1

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

Upvotes: 0

dougajmcdonald
dougajmcdonald

Reputation: 20037

I'd be checking this.state.restaurants in componentDidUpdate as that's the best way to see if your component has been updated.

It feels like you're doing things correctly if your first log is indeed correct (it seems an odd way to sort to me, I'd be calling array.sort() on the newRestaurants).

Maybe somewhere after your component updates, something is setting the restaurants back to it's original value again.

Upvotes: 1

marzelin
marzelin

Reputation: 11600

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>

Upvotes: 0

Related Questions