我正在尝试实现排序算法并构建 React 应用程序以显示未排序的数组如何随着每次迭代而变化。
为了使其可见,应用程序必须在每次迭代后停止一段时间,我正在尝试使用 setTimeout 函数和 useEffect 挂钩来执行此操作,但它不起作用。
这是我的组件:
import { useEffect, useState } from "react"
import { SortAlgorithms } from "../Utils/Sort"
export default function SortingBoard(){
const [board, setBoard] = useState([10,9,8,7,6,5,4,3,2,1])
const [delay, setDelay] = useState(500)
const [algorithm, setAlgorithm] = useState(() => SortAlgorithms[0])
const [isIterating, setIsIterating] = useState(false)
useEffect(() => {
async function sleep(){
const timer = new Promise(r => setTimeout(r, delay));
await timer
}
sleep()
}, [board])
const handleSort = async () => {
setIsIterating(true)
algorithm({board, setBoard})
setIsIterating(false)
}
return (
<div className="bord-layout">
<div className="bord">
{board.map( (item, idx) =>{
return <h1 key={idx}>{item}</h1>
})}
</div>
<div className="bord-options">
<select name="algorithms" onChange={e => setAlgorithm(() => SortAlgorithms[e.target.value])}>
<option value={0}>Bubble Sort</option>
<option value={1}>Sellection Sort</option>
</select>
<button disabled={isIterating} onClick={handleSort}>
Sort
</button>
</div>
</div>
)
}
这里是排序函数:
function BubbleSort({board, setBoard}){
for(let i = 0; i < board.length; i++){
for(let j = 0; j < board.length - 1; j++){
if(board[j] > board[j + 1]){
const temp = board[j]
board[j] = board[j + 1]
board[j + 1] = temp
setBoard([...board])
}
}
}
}
function SelectionSort({board, setBoard}){
for(let i = 0; i < board.length; i++){
let min = i
for(let j = i + 1; j < board.length; j++){
if( board[j] < board[min]){
min = j
}
}
const temp = board[i]
board[i] = board[min]
board[min] = temp
setBoard([...board])
}
}
export const SortAlgorithms = [BubbleSort, SelectionSort]
特别是,它在每次迭代时调用 setTimeout 但不等待它们解决。
在这种情况下我应该使用 useEffect 和 setTimeout 还是我可以使用其他方法?
您当前实现的问题是排序算法是同步的,您正试图在 useEffect 中使用 setTimeout,这实际上不会影响排序算法的同步执行。要解决此问题,您可以在排序算法本身中使用 setTimeout 并使它们异步。
你的排序算法应该是这样的:
async function BubbleSort({ board, setBoard }) {
const delay = 500;
const newBoard = [...board];
for (let i = 0; i < newBoard.length; i++) {
for (let j = 0; j < newBoard.length - 1; j++) {
if (newBoard[j] > newBoard[j + 1]) {
const temp = newBoard[j];
newBoard[j] = newBoard[j + 1];
newBoard[j + 1] = temp;
await new Promise((resolve) => setTimeout(resolve, delay));
setBoard([...newBoard]);
}
}
}
}
async function SelectionSort({ board, setBoard }) {
const delay = 500;
const newBoard = [...board];
for (let i = 0; i < newBoard.length; i++) {
let min = i;
for (let j = i + 1; j < newBoard.length; j++) {
if (newBoard[j] < newBoard[min]) {
min = j;
}
}
const temp = newBoard[i];
newBoard[i] = newBoard[min];
newBoard[min] = temp;
await new Promise((resolve) => setTimeout(resolve, delay));
setBoard([...newBoard]);
}
}
您现在可以删除具有睡眠功能的 useEffect 块,因为它不再需要了。此外,您需要使 handleSort 异步并等待对算法的调用:
const handleSort = async () => {
setIsIterating(true);
await algorithm({ board, setBoard });
setIsIterating(false);
};
进行这些更改时,排序算法现在将在每次迭代之间暂停指定的延迟,并且组件将相应地重新渲染。