0

I have a handler that changes some state of my react application, let's say it shuffles state entry data:

state = {
   data:[1,2,3,4,5]
  };

 public handleShuffle = () => {
    const current = this.state.data;
    const shuffled = current
      .map((a: any) => [Math.random(), a])
      .sort((a: any, b: any): any => a[0] - b[0])
      .map((a: any) => a[1]);
    this.setState({
      ...this.state,
      data: shuffled
    });
    consoleLog(this.state.data[0])
  };

Is there a way to access this new shuffled array still in this handler so there is a log of not 1 which is previous state, but a new shuffled one?

Dimitry Ivashchuk
  • 635
  • 2
  • 7
  • 23

3 Answers3

1

setState accepts a second callback argument when you pass an object as the first:

this.setState({ data: shuffled }, () => {
  this.state.data === shuffled // true
}

Assuming you're in the same scope, you don't actually need the callback since you already have the value of the soon-to-be state in shuffled and you can continue to use it.

Generally if you want to wait until this.state is updated and the component has been re-rendered it's recommended that you use componentDidUpdate instead of the setState callback.

Note that setState will already do a shallow diff on the object you pass in and merge in new updates. You don't need to do this: setState({ ...this.state }), and doing so is in fact harmful.

coreyward
  • 77,547
  • 20
  • 137
  • 166
1

You can pass second argument to setState. Please try this:

this.setState({
  ...this.state,
  data: shuffled
}, () => console.log(this.state.data[0]));
Sergii Vorobei
  • 1,477
  • 13
  • 19
0

The state update is async and setState has a callback

try this

public handleShuffle = () => {
const current = this.state.data;
const that = this;
const shuffled = current
  .map((a: any) => [Math.random(), a])
  .sort((a: any, b: any): any => a[0] - b[0])
  .map((a: any) => a[1]);
this.setState({
  ...this.state,
  data: shuffled
}, ()=>{
   consoleLog(that.state.data[0])
});
};
Tiisetso Tjabane
  • 2,088
  • 2
  • 19
  • 24