0

I am trying to implement sorting algorithms and build react app to display how unsorted array is changing with each iteration.

To make it visible, app has to stop for some time after every iteration and I'm trying to do this with setTimeout function and useEffect hook but it doesn't work.

Here is my component:

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

Here are sort functions:

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] 

In particular, it calls setTimeout on every iteration but doesn't wait for them to resolve.

Should i use useEffect and setTimeout in this case or there is other approach I can use?

1
  • What do you mean each iteration? Your sleep() right now is just a timeout that does nothing asynchronously every time your board changes. When your board changes, the component re-renders, and your effects run, and your timeout runs but doesn't do anything, and won't block anything. If you want to sleep every time your for loop runs, you need to fundamentally rewrite your sorting to put the timeout in there, and use callbacks and saving state rather than a for loop. You're probably better off with a simple console.log Commented Apr 13, 2023 at 23:49

1 Answer 1

0

The problem with your current implementation is that the sort algorithms are synchronous and you are trying to use setTimeout inside the useEffect which really doesn't affect the synchronous execution of the sort algorithms. To fix this you can use setTimeout in the sort algorithms themselves and make them asynchronous.

Your sorting algorithms should look like this:

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

You can now remove the useEffect block with the sleep function as it is no longer needed. Also, you need to make handleSort asynchronous and wait for the call to the algorithm:

const handleSort = async () => { setIsIterating(true); await algorithm({ board, setBoard }); setIsIterating(false); }; 

When making these changes, the sorting algorithms will now pause for the specified delay between each iteration and the component will re-render accordingly.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.