我最近开始使用React,并且遇到了一个看似与状态变量有关的问题。

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


在这里,我尝试使用从功能bubbleSort返回的信息更新状态。问题是,bubbleSort的结果很奇怪:
我期望一个数组数组,其中每个单独的数组代表排序过程中列表的快照。理想情况下,我会将每个快照用作动画的框架,但实际上,返回的数组由排序的最终结果的多个副本组成。这很奇怪,特别是因为随着排序的进行,我明确尝试保存原始步骤和中间步骤。请参阅底部的bubbleSort()代码。

我知道这里有很多文字,但是非常感谢帮助您了解正在发生的事情,我很茫然。谢谢!

编辑:

我正在添加bubbleSort()的代码,以提供更多信息。

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

最佳答案

我认为它的工作方式与您期望的一样,但是控制台在更改值之后会检查该值。

如果bubbleSort()改变了数据的原位,而不是返回进行了编辑的新原始副本,则控制台将仅保留对象引用,然后在检查时显示其当前值。

这是您要一成不变地对待状态的原因之一,还有许多其他原因。切勿更改状态中的对象。始终提供新对象。

我敢打赌这将解决您的问题:

bubbleSort([...members]);


但是您可能应该实现冒泡排序,以返回新的数组或对象,而不是修改现有的数组或对象。

没有bubbleSort的来源,我不能肯定地说这是正确的。但是我以前见过这种行为,这就是原因。

关于javascript - ReactJS-状态变量行为异常,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60011129/

10-09 07:29