ReactJS: 如何设置一个for循环每秒循环一次?

huangapple go评论76阅读模式
英文:

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'>&#127362;&#127358;&#127361;&#127363;&#127352;&#127357;&#127350; &#127344;&#127355;&#127350;&#127358;&#127361;&#127352;&#127363;&#127351;&#127356; &#127365;&#127352;&#127362;&#127364;&#127344;&#127355;&#127352;&#127369;&#127348;&#127361;</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 &#39;@/components/sorting-algorithm&#39;
import { Inter } from &#39;next/font/google&#39;

const App: React.FC = () =&gt; {
  return(
    &lt;div className=&#39;headerContainer&#39;&gt;
      &lt;h1 className=&#39;header&#39;&gt;&#127362;&#127358;&#127361;&#127363;&#127352;&#127357;&#127350; &#127344;&#127355;&#127350;&#127358;&#127361;&#127352;&#127363;&#127351;&#127356; &#127365;&#127352;&#127362;&#127364;&#127344;&#127355;&#127352;&#127369;&#127348;&#127361;&lt;/h1&gt;
      &lt;SortingAlgorithm /&gt;
    &lt;/div&gt;
  )
}

export default App;

sorting-algorithm.tsx

import { Inter } from &#39;next/font/google&#39;
import React, { useState, useEffect } from &#39;react&#39;

const SortingAlgorithm: React.FC = () =&gt; {
  const [arr, setArr] = useState&lt;number[]&gt;([3, 1, 2, 5, 4]);

  //Selection sort
  while (arr != arr.sort()) {
    useEffect(() =&gt; {
      for (let i = 0; i &lt; arr.length; i++) {
        const loop = setTimeout(() =&gt; {
        let minIndex: number = i;
        for (let j = i + 1; j &lt; arr.length; j++) {
          if (arr[j] &lt; arr[minIndex]) {
            minIndex = j;
          }
        }
        let temp: number = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
        }, 1000);

        return() =&gt; clearTimeout(loop);
      }
    }, []);
  }
  
  return arr.map&lt;JSX.Element&gt;((keys) =&gt; (
    &lt;div className=&#39;barsContainer&#39;&gt;
      &lt;svg className=&#39;bars&#39;&gt;
        &lt;rect height={keys * 25} width={100 - (arr.length * 10)} x={arr.indexOf(keys) * 53} y={0}/&gt;
      &lt;/svg&gt;
    &lt;/div&gt;
  ))
}

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的一些建议:

  1. 永远不要在控制流结构中使用钩子,比如ifwhile等。必须在每次React函数执行时执行钩子,以使它们正常工作。如果检查开发者控制台,可能会看到React的警告或错误信息。
  2. 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 &quot;react&quot;;
function() {

  const [state, setState] = useState(0);

  useEffect(() =&gt;{
    const id = setTimeout(() =&gt; {
      setState(state + 1);
    }, 500);
    return () =&gt; clearTimeout(id);
  }, [state])

  return (
    &lt;div&gt;
      &lt;span&gt;Counter&lt;/span&gt;
      {` `}
      {state}
    &lt;/div&gt;
  );
});

A few notes on hooks:

  1. Never use a hook in a control flow structure such
    as if, 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.
  2. React depends on setState to know when to update your component. Since you never call setArr, 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(() =&gt; {
for (let i = 0; i &lt; arr.length; i++) {
  setTimeout(() =&gt; {
    setArr(arr =&gt; {
      let arrCopy: number[] = [...arr];
      let minIndex: number = i;
      for (let j = i + 1; j &lt; arr.length; j++) {
        if (arrCopy[j] &lt; arrCopy[minIndex]) {
          minIndex = j;
        }
      }
    let temp: number = arrCopy[i];
    arrCopy[i] = arrCopy[minIndex];
    arrCopy[minIndex] = temp;

    return arrCopy;
    })
  }, 100 * (i + 1));
}

}, []);

huangapple
  • 本文由 发表于 2023年3月7日 09:50:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75657367.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定