英文:
ReactJS: How do I set a for loop to loop once every second?
问题
I am trying to build a sorting algorithm visualizer that represents the values of an array as rectangles with different heights corresponding to each element's value. It's supposed to show each step of the algorithm's process, with every loop occurring after a second has passed. However, whenever the web page loads, the array is already sorted. I want to make it so that after every second, the position of the rectangle being sorted changes so that each step of the sorting algorithm is being shown. My code is below:
index.tsx
import SortingAlgorithm from '@/components/sorting-algorithm'
import { Inter } from 'next/font/google'
const App: React.FC = () => {
return (
<div className='headerContainer'>
<h1 className='header'>🆂🅾🆁🆃🅸🅽🅶 🅰🅻🅶🅾🆁🅸🆃🅷🅼 🆅🅸🆂🆄🅰🅻🅸🆉🅴🆁</h1>
<SortingAlgorithm />
</div>
)
}
export default App;
sorting-algorithm.tsx
import { Inter } from 'next/font/google';
import React, { useState, useEffect } from 'react';
const SortingAlgorithm: React.FC = () => {
const [arr, setArr] = useState<number[]>([3, 1, 2, 5, 4]);
// Selection sort
while (arr != arr.sort()) {
useEffect(() => {
for (let i = 0; i < arr.length; i++) {
const loop = setTimeout(() => {
let minIndex: number = i;
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
let temp: number = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}, 1000);
return () => clearTimeout(loop);
}
}, []);
}
return arr.map<JSX.Element>((keys) => (
<div className='barsContainer'>
<svg className='bars'>
<rect height={keys * 25} width={100 - (arr.length * 10)} x={arr.indexOf(keys) * 53} y={0}/>
</svg>
</div>
));
}
export default SortingAlgorithm;
I've already implemented setTimeout
inside the for loop containing the sorting algorithm. I thought it would be the perfect solution to my problem, yet it seems that it doesn't alter the speed at which the for loop loops. I've also tried playing around with the syntax, though that doesn't really seem to make a difference. A point in the right direction at least would be greatly appreciated.
英文:
I am trying to build a sorting algorithm visualizer that represents the values of an array as rectangles with different heights corresponding to each element's value. It's supposed to show each step of the algorithm's process, with every loop occurring after a second has passed. However, whenever the web page loads, the array is already sorted. I want to make it so that after every second, the position of the rectangle being sorted changes so that each step of the sorting algorithm is being shown. My code is below:
index.tsx
import SortingAlgorithm from '@/components/sorting-algorithm'
import { Inter } from 'next/font/google'
const App: React.FC = () => {
return(
<div className='headerContainer'>
<h1 className='header'>🆂🅾🆁🆃🅸🅽🅶 🅰🅻🅶🅾🆁🅸🆃🅷🅼 🆅🅸🆂🆄🅰🅻🅸🆉🅴🆁</h1>
<SortingAlgorithm />
</div>
)
}
export default App;
sorting-algorithm.tsx
import { Inter } from 'next/font/google'
import React, { useState, useEffect } from 'react'
const SortingAlgorithm: React.FC = () => {
const [arr, setArr] = useState<number[]>([3, 1, 2, 5, 4]);
//Selection sort
while (arr != arr.sort()) {
useEffect(() => {
for (let i = 0; i < arr.length; i++) {
const loop = setTimeout(() => {
let minIndex: number = i;
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
let temp: number = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}, 1000);
return() => clearTimeout(loop);
}
}, []);
}
return arr.map<JSX.Element>((keys) => (
<div className='barsContainer'>
<svg className='bars'>
<rect height={keys * 25} width={100 - (arr.length * 10)} x={arr.indexOf(keys) * 53} y={0}/>
</svg>
</div>
))
}
export default SortingAlgorithm;
I've already implemented setTimeout
inside the for loop containing the sorting algorithm. I thought it would be the perfect solution to my problem, yet it seems that it doesn't alter the speed at which the for loop loops. I've also tried playing around with the syntax, though that doesn't really seem to make a difference. A point in the right direction at least would be greatly appreciated.
答案1
得分: 1
这是一个关于完整解决方案的示例实现。
请查看下面的示例,其中包含一个计数器,以最基本的形式演示了您试图实现的内容:
import React, { useEffect, useState } from "react";
function() {
const [state, setState] = useState(0);
useEffect(() =>{
const id = setTimeout(() => {
setState(state + 1);
}, 500);
return () => clearTimeout(id);
}, [state])
return (
<div>
<span>Counter</span>
{` `}
{state}
</div>
);
});
关于Hooks的一些建议:
- 永远不要在控制流结构中使用钩子,比如
if
,while
等。必须在每次React函数执行时执行钩子,以使它们正常工作。如果检查开发者控制台,可能会看到React的警告或错误信息。 - React依赖于
setState
来知道何时更新您的组件。由于您从未调用setArr
,因此您的组件从未更新。请查看setState。
考虑阅读有关Hooks的完整文档,以便完全了解它们的预期用途。
英文:
Here is a sample implementation for a full solution.
Below, please see this minimal example with a counter that demonstrates in its most basic form what you are trying to accomplish:
import React, { useEffect, useState } from "react";
function() {
const [state, setState] = useState(0);
useEffect(() =>{
const id = setTimeout(() => {
setState(state + 1);
}, 500);
return () => clearTimeout(id);
}, [state])
return (
<div>
<span>Counter</span>
{` `}
{state}
</div>
);
});
A few notes on hooks:
- Never use a hook in a control flow structure such
asif
,while
, etc. A hook must be executed every single time
your react function executes in order for them to work properly. If
you check your dev console, you may see React warning or erroring
about this. - React depends on
setState
to know when to update your component. Since you never callsetArr
, your component never updates. See setState
Consider reading the full documentation on hooks so you can develop a complete understanding of their intended uses.
答案2
得分: 0
我根据另一个Stackoverflow帖子找到了要做的事情。我决定将我的代码贴在下面,以防有人遇到相同的问题,这是他们第一次找到的东西。
useEffect(() => {
for (let i = 0; i < arr.length; i++) {
setTimeout(() => {
setArr(arr => {
let arrCopy: number[] = [...arr];
let minIndex: number = i;
for (let j = i + 1; j < arr.length; j++) {
if (arrCopy[j] < arrCopy[minIndex]) {
minIndex = j;
}
}
let temp: number = arrCopy[i];
arrCopy[i] = arrCopy[minIndex];
arrCopy[minIndex] = temp;
return arrCopy;
})
}, 100 * (i + 1));
}
}, []);
英文:
I figured out what to do based off of another Stackoverflow post. I've decided to post my code below just in case someone else had the same issue and this is the first thing they find.
useEffect(() => {
for (let i = 0; i < arr.length; i++) {
setTimeout(() => {
setArr(arr => {
let arrCopy: number[] = [...arr];
let minIndex: number = i;
for (let j = i + 1; j < arr.length; j++) {
if (arrCopy[j] < arrCopy[minIndex]) {
minIndex = j;
}
}
let temp: number = arrCopy[i];
arrCopy[i] = arrCopy[minIndex];
arrCopy[minIndex] = temp;
return arrCopy;
})
}, 100 * (i + 1));
}
}, []);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论