我正在尝试使用冒泡排序对数组进行排序,并且在排序的每个步骤中,我都希望呈现数组内值位置的变化。 所以用 React 做了下面的算法,第一次它确实渲染了变化,但后来停止了,不渲染任何东西。我试图控制台记录我正在渲染的数组,我正在控制台上获取每个排序步骤,但不知道为什么它在这里不起作用。 谁能告诉我为什么会这样?还有什么可以做的?
注意:它最初工作正常并呈现排序数组,但后来当我添加 setTimeOut
函数时它不起作用。
App.js
import React, { useState } from "react";
const App = () => {
const [arrayForSort, setArrayForSort] = useState([44,2,46,11,15,34,1,7,55]);
const fetchArray = arrayForSort.map((element) => {
return <span>{element} </span>;
});
const bubbleSort = (array) => {
let newArray = [...array];
let n = newArray.length;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n - i; j++) {
const myVar = setTimeout(() => {
if (newArray[j] > newArray[j + 1]) {
[newArray[j], newArray[j + 1]] = [newArray[j + 1], newArray[j]];
}
console.log(newArray); // render each step of sort
setArrayForSort(newArray); // on screen it just shows "2 44 46 11 15 34 1 7 55" the very first step of sort
}, 2000);
}
}
};
return (
<div>
<h4>Array: </h4>
<span>{fetchArray}</span>
<div>
<button
onClick={() => {
bubbleSort(arrayForSort);
}}
>
Sort
</button>
</div>
</div>
);
};
export default App;
答案 0 :(得分:1)
您的代码几乎没有问题。 2000
是一个常量值,这意味着您的所有 setTimeout
会在 2 秒后一起触发。这就是为什么您的所有 console.logs
同时出现的原因。
其次,setTimeout
将保留 setArrayForSort
的引用。但是每次渲染后都需要一个新的参考。如果您使用类组件,但使用功能组件,您需要以不同的方式思考,这可能会起作用。
这是一个工作演示codesandbox link
import React, { useEffect, useRef, useState } from "react";
const App = () => {
const [arrayForSort, setArrayForSort] = useState([44, 2, 46, 11, 15, 34, 1, 7, 55]);
const ijRef = useRef({ i: 0, j: 0 });
const [isSorting, setIsSorting] = useState(false);
const fetchArray = arrayForSort.map((element) => {
return <span key={element}>{element} </span>;
});
useEffect(() => {
if (!isSorting) return;
const ij = ijRef.current;
const i = ij.i;
const j = ij.j;
const arr = [...arrayForSort];
const n = arr.length;
let isSwapped = false;
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
isSwapped = true;
}
if (j < n - i) {
ij.j++;
} else if (ij.i < n) {
ij.j = 0;
ij.i++;
}
// This will trigger the next render
// and loop will continue until ij.i < n
setTimeout(
() => {
if (ij.i >= n) {
setIsSorting(false);
}
setArrayForSort(arr);
},
isSwapped ? 100 : 0 // delay 100ms for a successful swap
);
}, [ijRef, arrayForSort, setArrayForSort, isSorting]);
const beginSort = () => {
ijRef.current.i = 0;
ijRef.current.j = 0;
setIsSorting(true); // begin sorting
};
return (
<div>
<h4>Array: </h4>
<span>{fetchArray}</span>
<div>
<button onClick={beginSort}>Sort</button>
</div>
</div>
);
};
export default App;