Reactjs 反应-排序时元素未就位

Reactjs 反应-排序时元素未就位,reactjs,sorting,visualization,Reactjs,Sorting,Visualization,我正在学习react,并决定尝试创建一个排序可视化工具。我从bubble sort开始,几乎成功地创建了一个基本的可视化工具。我添加了更改排序速度和排序数组长度的选项。我对它进行了几次测试,发现有时在显示已排序的数组时,某些元素不在适当的位置。当您的高元素不在其应该的位置时(场景后面的数组本身已正确排序),可以看到这一点。所以显示元素发生了一些事情,我不知道是什么。 排序完成后,如果某些元素不在适当的位置,如果我突然改变速度,元素会跳回到它们应该在的位置。我猜这是因为速度是国家的一部分,重新定义

我正在学习react,并决定尝试创建一个排序可视化工具。我从bubble sort开始,几乎成功地创建了一个基本的可视化工具。我添加了更改排序速度和排序数组长度的选项。我对它进行了几次测试,发现有时在显示已排序的数组时,某些元素不在适当的位置。当您的高元素不在其应该的位置时(场景后面的数组本身已正确排序),可以看到这一点。所以显示元素发生了一些事情,我不知道是什么。 排序完成后,如果某些元素不在适当的位置,如果我突然改变速度,元素会跳回到它们应该在的位置。我猜这是因为
速度
是国家的一部分,重新定义正在发生。
我该怎么做才能解决这个问题

这是我的密码:

import React, { useContext, useState, useEffect } from 'react';

const NUMBER_OF_ELEMENTS = 10;

const DEFAULT_COLOR = 'white';
const COMPARE_COLOR = 'darkred';
const DONE_COLOR = 'green';

const SPEED = 4;

const SPEEDS = [1, 5, 10, 25, 50, 100, 150, 200, 250, 300];

const randomIntFromInterval = (min, max) => {
    return Math.floor(Math.random() * (max - min + 1) + min);
}

const Dummy = () => {
    const [arr, setArr] = useState([]);
    const [numberOfElements, setNumberOfElements] = useState(NUMBER_OF_ELEMENTS);
    const [speed, setSpeed] = useState(SPEED);

    const timeout_id = [];

    useEffect(() => {
        generateArray();
    }, [numberOfElements]);

    const reset = () => {
        resetColors();
        generateArray();
    }

    const generateArray = () => {
        const arr1 = [];
        for(let i = 0; i < numberOfElements; i++)
        {
            arr1[i] = randomIntFromInterval(5, 100);
        }
        console.log(arr1);
        setArr(arr1);
    }

    const resetColors = () => {
        const arrayBars = document.getElementsByClassName('array-bar');
        for(let i = 0; i < arrayBars.length; i++) {
            arrayBars[i].style.backgroundColor = DEFAULT_COLOR;
        }
    }

    const bubbleSort = (arr, n) => {
        let i, j, temp, swapped, delay = 1;
        for(i = 0; i < n - 1; i++) 
        {
            swapped = false;
            for(j = 0; j < n - i - 1; j++) 
            {
                createColor([j, j + 1], COMPARE_COLOR,  delay++);
                if(arr[j] > arr[j + 1]) 
                {
                    // swap arr[j] and arr[j+1] 
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                    createAnimation(j, j + 1, delay++);
                }
                createColor([j, j + 1], DEFAULT_COLOR, delay++);
            }
            createColor([n - i - 1], DONE_COLOR, delay++);

            // If no two elements were  
            // swapped by inner loop, then break 
            if(swapped === false) break;
        }

        const leftovers = [];
        for(let k = 0; k < n - i - 1; k++) {
            leftovers.push(k);
        }

        createColor(leftovers, DONE_COLOR, delay++);
    }

    const createAnimation = (one, two, delay) => {
        const arrayBars = document.getElementsByClassName('array-bar');
        const id = setTimeout(() => {
            const barOneHeight = arrayBars[one].style.height;
            const barTwoHeight = arrayBars[two].style.height;
            arrayBars[two].style.height = `${barOneHeight}`;
            arrayBars[one].style.height = `${barTwoHeight}`;
        }, SPEEDS[speed - 1] * delay);
        timeout_id.push(id);
    }

    const createColor = (indexes, color, delay) => {
        const arrayBars = document.getElementsByClassName('array-bar');
        const id = setTimeout(() => {
            for(let i = 0; i < indexes.length; i++) {
                arrayBars[indexes[i]].style.backgroundColor = color;
            }
        }, SPEEDS[speed - 1] * delay);
        timeout_id.push(id);
    }

    const handleSort = (arr) => {
        bubbleSort(arr, arr.length);
    }

    const handlerRange = (e) => {
        setNumberOfElements(e.target.value);
    }

    const stopTimeOuts =() => {
        for(let i = 0; i < timeout_id.length; i++) {
            clearTimeout(timeout_id[i]);
        }
    }

    const handleSpeed = (e) => {
        setSpeed(e.target.value);
    }

    const maxVal = Math.max(...arr);

    return (
        <div>
            <div className="array-container" style={{height: '50%', backgroundColor: 'black'}}>
                {arr.map((value, idx) => (
                    <div className="array-bar"
                         key={idx}
                         style={{
                            backgroundColor: DEFAULT_COLOR,
                            height: `${(value * 100 / maxVal).toFixed()}%`,
                            width: `${85 / arr.length}%`,
                            display: 'inline-block',
                            margin: '0 1px'
                         }}>
                    </div>
                ))}
            </div>

            <div className="buttons-container">
                <button onClick={() => handleSort(arr)}>Sort!</button>
                <button onClick={() => reset()}>Reset</button>
                <button onClick={() => stopTimeOuts()}>Stop!</button>
            </div>

            number of elements: {numberOfElements}
            <div className="slider-container">
                1
                <input type="range" 
                       min="1" 
                       max="100" 
                       onChange={(e) => handlerRange(e)} 
                       className="slider" 
                       id="myRange" 
                />
                100
            </div>

            speed: {speed}
            <div className="slider-container">
                1
                <input type="range" 
                       min="1" 
                       max="10" 
                       onChange={(e) => handleSpeed(e)} 
                       className="slider" 
                       id="myRange" 
                />
                10
            </div>

        </div>
    );
}

export default Dummy;
import React,{useContext,useState,useffect}来自“React”;
元素的常数个数=10;
常量默认颜色='白色';
const COMPARE_COLOR='darkred';
const DONE_COLOR='绿色';
恒速=4;
常数速度=[1,5,10,25,50,100,150,200,250,300];
常量randomIntFromInterval=(最小值,最大值)=>{
返回Math.floor(Math.random()*(max-min+1)+min);
}
常量虚拟=()=>{
const[arr,setArr]=useState([]);
常量[numberOfElements,setNumberOfElements]=useState(元素的数量);
常数[速度,设定速度]=使用状态(速度);
常量超时_id=[];
useffect(()=>{
generatarray();
},[numberOfElements]);
常数重置=()=>{
重置颜色();
generatarray();
}
const generatarray=()=>{
常数arr1=[];
for(设i=0;i{
const arrayBars=document.getElementsByClassName('array-bar');
for(设i=0;i{
设i,j,temp,swapped,延迟=1;
对于(i=0;iarr[j+1])
{
//交换arr[j]和arr[j+1]
温度=arr[j];
arr[j]=arr[j+1];
arr[j+1]=温度;
交换=真;
createAnimation(j,j+1,delay++);
}
createColor([j,j+1],默认颜色,延迟++);
}
createColor([n-i-1],DONE_COLOR,delay++);
//如果没有两个元素
//由内部循环交换,然后断开
如果(交换===假)中断;
}
常量剩余=[];
for(设k=0;k{
const arrayBars=document.getElementsByClassName('array-bar');
const id=setTimeout(()=>{
const barOneHeight=arrayBars[one].style.height;
const barTwoHeight=arrayBars[two].style.height;
arrayBars[two].style.height=`${barOneHeight}`;
arrayBars[one].style.height=`${barTwoHeight}`;
},速度[速度-1]*延迟);
超时\u id.push(id);
}
const createColor=(索引、颜色、延迟)=>{
const arrayBars=document.getElementsByClassName('array-bar');
const id=setTimeout(()=>{
for(设i=0;i{
气泡运动(arr,arr.length);
}
常量handlerRange=(e)=>{
setNumberOfElements(如目标值);
}
常量停止超时=()=>{
for(设i=0;i{
设定速度(如目标值);
}
const maxVal=Math.max(…arr);
返回(
{arr.map((值,idx)=>(
))}
handleSort(arr)}>排序!
reset()}>reset
停止超时()}>停止!
元素数:{numberOfElements}
1.
handlerRange(e)}
className=“滑块”
id=“myRange”
/>
100
速度:{speed}
1.
无手柄速度(e)}
className=“滑块”
id=“myRange”
/>
10
);
}
导出默认虚拟;

将div内部的键设置为唯一标识符,而不是
idx
-在这种情况下,您可以使用

/* -- snip -- */
<div className="array-bar"
     key={value}
/* -- snip -- */
/*--snip--*/

回答得好!帮我解决了这个问题,谢谢。将
重分类为键,我不确定它在这种情况下是否有效,因为
在数组中不一定是唯一的。对,但它仍然有效,因为在您的示例中,div中唯一的数据是值。因此,两个10值完全相同,并且顺序应该相同(在您的示例中)。但是,如果div中有其他数据,那么您可能希望生成一个真正唯一的标识符,例如的uuid
<div id=1>Foo</div> // Id "1" is now bound to this element
<div id=2>Bar</div>
<div id=1>Bar</div> // this will be transformed to <div id=1>Foo</div>
<div id=2>Foo</div> // this will be transformed to <div id=2>Bar</div>