Beginner
Beginner

Reputation: 202

How to set state inside a loop with a time delay in react js

I was trying to make a program to visualize bubble sort in ReactJS for which I'm trying to update the state of array inside a loop with some delay. But the state of the array is only updated once. I don't understand what's wrong with it. Is this way wrong for updating the state in react?

I'm updating the state of array inside useEffect() and I'm calling the bubbleSort() by "onClick" event

import {useState, useEffect, useRef} from 'react'

function App() {

  let count = 0;
  const [array, setArray] = useState([])
  const barBoundary = useRef(null)

  useEffect(()=>{
    count = 0;
    setArray(generateArray(1,100,400))
  }, [])


  const generateArray = (min, max,l) => {
    return Array.from({length: l}, () => Math.floor(Math.random() * (max - min) + min));
  }

  const sleep = (milli) => {
    return new Promise(resolve => setTimeout(resolve, milli)
  }

  const bubbleSort = async (speed) => {
    let temp = [...array];
    let len = array.length;
    let checked;
    do {
        checked = false;
        for (let i = 0; i < len; i++) {
            if (temp[i] > temp[i + 1]) {
              
              let tmp = temp[i];
              temp[i] = temp[i + 1];
              temp[i + 1] = tmp;
              await sleep(10)
              setArray(temp)
              checked = true;   
            }
            
        }
    } while (checked);
  }

  return (
    <div className="App">
      
      <div className="container">
        <div className="navbar">
          <ul>
            <li><button onClick={()=> setArray(generateArray(1,100,700))}>Bubble Sort</button></li>
            <li><button onClick={()=>bubbleSort()}>Sort</button></li>
          </ul>
        </div>
        <div className="bar-container">
          <div className="bar-boundary" ref={barBoundary}>
            <div className="bars">
              {
                array.map(item => {
                  return(
                  <div className="bar" key={++count}
                    style={{
                      backgroundColor:"blue",
                      height:`${item}%`,
                    }}
                  >
                  </div>)
                })
              }
            </div>
          </div>
        </div>
      </div>
      
    </div>
  );
}

export default App;

Upvotes: 1

Views: 851

Answers (1)

Amila Senadheera
Amila Senadheera

Reputation: 13245

This is the issue, your array is referring to the same instance and does not re-render. Create a new array from temp array and set the state. It worked.

setArray([...temp])

Upvotes: 2

Related Questions