ReactJS - State variables acting strangely

AndresB

I've started using React recently and have run into a problem seemingly related to state variables.

    bSort(){

        this.setState(
            state => {
                console.log("PRE BSORT STATE", state)
                let current_members = [...state.members];
                console.log("members pre BSORT", current_members);
                const updated_states = bubbleSort([...current_members]);
                return {states: updated_states, animate : true};
            },
            () => this.animate()
          );
    }

Here, I'm trying to update my state using information returned from the function bubbleSort. The issue is that the result of bubbleSort is strange: I'm expecting an array of arrays, where each individual array represents a snapshot of the list as the sort progresses. Ideally, I would use each of these snapshots as a frame for my animation, but in reality the returned array is composed of multiple copies of the final result of the sort. This is odd, specially since I explicitly try to save the original and middle steps as the sort progresses. Please see the bubbleSort() code at the bottom.

I know there is a lot of text here but I would much appreciate help understanding what is happening, I am at a loss. Thank you!

EDIT:

I am adding the code for bubbleSort() so as to provide more information.

export default function bubbleSort(list){
    let members = [...list];
    let frames= [];
    //the original order of the members should be the first frame in the list
    frames.push(members);

    let early_exit = false;
    let wall = members.length;

    while(!early_exit){

        console.log("FRAMES WITHIN BSORT", frames);

        let last_change_index = null;
        for(var i = 0; i < wall; i++){
            if(members[i+1] != null){

                console.log("COMPARING", members[i].props.style.height, "AND", members[i+1].props.style.height);

                //Here we color red the two elements that will be compared
                var new_1 = React.cloneElement(
                    members[i],
                    {
                        style : {backgroundColor : "red", height : members[i].props.style.height}
                    }
                );
                var new_2 = React.cloneElement(
                    members[i+1],
                    {
                        style : {backgroundColor : "red", height : members[i+1].props.style.height}
                    }
                );
                members[i] = new_1;
                members[i+1] = new_2;

                //and add this new comparison state to the list of frames
                frames.push(members);

                //now we decide if we need to swap the elements
                if(members[i].props.style.height > members[i+1].props.style.height){

                    console.log("SWAPPING", i, i+1);
                    //If should swap, the two elements are colored yellow and shifted on the x axis
                    let new_1_yellow = React.cloneElement(
                        new_1,
                        {
                            animate : {x : 3},
                            style : {backgroundColor : "yellow", height : new_1.props.style.height}
                        }
                    );
                    let new_2_yellow = React.cloneElement(
                        new_2,
                        {
                            animate : {x : -3},
                            style : {backgroundColor : "yellow", height : new_2.props.style.height}
                        }
                    );

                    members[i+1] = new_1_yellow;
                    members[i] = new_2_yellow;

                    last_change_index = i;

                    frames.push(members);

                    //We change the yellow swapped members back to blue
                    let new_1_blue = React.cloneElement(
                        new_1_yellow,
                        {
                            animate : {x : 0},
                            style : {backgroundColor : "blue", height : new_1_yellow.props.style.height}
                        }
                    );

                    let new_2_blue = React.cloneElement(
                        new_2_yellow,
                        {
                            animate : {x : 0},
                            style : {backgroundColor : "blue", height : new_2_yellow.props.style.height}
                        }
                    );

                    members[i+1] = new_1_blue;
                    members[i] = new_2_blue;

                    //and add this return to blue state to the list
                    frames.push(members);

                }
                else{
                //Here we re-color blue the two elements that were compared
                    let new_1_blue = React.cloneElement(
                        new_1,
                        {
                            style : {backgroundColor : "blue", height : new_1.props.style.height}
                        }
                    );
                    let new_2_blue = React.cloneElement(
                        new_2,
                        {
                            style : {backgroundColor : "blue", height : new_2.props.style.height}
                        }
                    );
                    members[i] = new_1_blue;
                    members[i+1] = new_2_blue;

                    //and add this return to blue state to the list
                    frames.push(members);
                }
            }
        }
        if(last_change_index == null){
            early_exit = true;
        }
        wall = last_change_index;
    }
    return frames;
}
Alex Wayne

I think that it's working like you expect, but the console is inspecting the value after it changes.

If bubbleSort() mutates your data in place, rather then returning a new pristine copy with your edits made, then your console is just holding onto an object reference, and then showing it's current values when you inspect it.

This is one of the reasons, and there are many other reasons, that you want to treat state immutably. Never change objects in state. Always provide new objects in state.

I bet this will fix your problem:

bubbleSort([...members]);

But you should probably implement bubble sort to return a new array or object, rather than modify an existing one.

Without the source of bubbleSort I can't say for sure this is right. But I've seen this behaviour before and this was the cause.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related