skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    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));
    }
    

    }, []);


  2. 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:

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search