1

I am trying to partially change the state of my component, but unfortunately it isn't performing as I'm excpecting.

I initialize the state in this way :

constructor(props){
        super(props);
        this.state = {
            array: [],
            status: false,
            interval: null,
            animations: [],
            algorithm: null 
        }
    }

The way I try to use it

if(this.state.status === false){
            this.change_style(text);

            //The change
            this.setState({status: true, animations: [], algorithm: "Bubble_Sort"});

            const arr = this.state.array.slice();
            this.bubble_sort_and_push(this.state.animations, arr);
            this.animate(this.state.animations);
        }

After some research I saw that setState only changes the state if there is an actual change between the prev state to the new one (In my case it does have differences)

So I can't really grasp why the changes don't go through.

I tried changing only one of the fields

 if(this.state.status === false){
            this.change_style(text);
            console.log(this.state.status);
            //The change
            this.setState({status: true})
            console.log(this.state.status);

            const arr = this.state.array.slice();
            this.bubble_sort_and_push(this.state.animations, arr);
            this.animate(this.state.animations);
        }

There was no difference between the console.log calls, but the change did happen.

How can I make the setState perform the moment I invoke it?

I have tried using forceUpdate() and read that it has connection to DidComponentUpdate, but can't really figure out how to connect them to work like I expect.

Florian Motteau
  • 3,467
  • 1
  • 22
  • 42
abramzog
  • 27
  • 6
  • Possible Duplicate of [setState doesn't update the state immediately](https://stackoverflow.com/questions/41278385/setstate-doesnt-update-the-state-immediately/41278440#41278440) – Shubham Khatri Jun 07 '20 at 13:44

3 Answers3

0

setState is asynchronous, you should never assume that changes will be immediate :

https://reactjs.org/docs/react-component.html#setstate

React does some operations in the background, like bundling state changes together to be more efficient (update things in bulk).

In a functional component the solution would be to use the useEffect hook, with a non empty dependencies array. React would trigger useEffect when a variable in the dependencies array changes :

useEffect(() => {
  // code performed when stateVariable has changed
}, [stateVariable]);

In a class based component the solution would imply componentDidUpdate lifecycle method :

componentDidUpdate(prevProps, prevState, snapshot) {
  if (this.state.stateVariable !== prevState.stateVariable) {
    // code performed when stateVariable has changed
  }
}
Florian Motteau
  • 3,467
  • 1
  • 22
  • 42
0

You need to pass the code in a callback if you want it to be execute immediately after setState, your code would be something like this in Class Component:

 if(this.state.status === false){
            this.change_style(text);
            console.log(this.state.status);
            //The change
            this.setState({status: true}, function(){
                console.log(this.state.status);

                const arr = this.state.array.slice();
                this.bubble_sort_and_push(this.state.animations, arr);
                this.animate(this.state.animations);
            });
  }
Taghi Khavari
  • 6,272
  • 3
  • 15
  • 32
  • I can understand it, but sadly I don't really need the `console.log` call, I'm trying to make the state change, so i could use it in the lines that come after. – abramzog Jun 07 '20 at 14:16
  • what do you mean by `in the lines that come after` ? all the code inside `function callback` would be execute after `state change`. – Taghi Khavari Jun 07 '20 at 15:37
0

You can simply try this.setState({status: true},(this.state.status)=> console.log()) In your case, console log was getting rendered before setState was completing its job.

Snehal
  • 121
  • 6