Why does the sorting finish instantly? Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Why does the sorting finish instantly? without wasting too much if your time.

The question is published on by Tutorial Guruji team.

I’ve been trying to show every step of the sorting process of an array using react. I’ve implemented the bubble sort algorithm, but I noticed a very strange thing:

When I using this approach UI instantly show a sorted array:

function BubbleSort({ array }) {
  const [elements, setElements] = useState(array);

  const onSort = () => {
    console.log('onSort fired')
    const length = elements.length;
    const newElements = elements.slice();

    let swap = 0;

    for (let i = 0; i < length; i++) {
      for (let j = i + 1; j < length; j++) {
        if (newElements[i].value > newElements[j].value) {
          console.log('Swap fired', swap);

          const buffer = newElements[i];
          newElements[i] = newElements[j];
          newElements[j] = buffer;

          swap++
          
          setTimeout(() => setElements(newElements.slice()), 1000 * swap);

        }
      }
    }
  }

  return (
    <ArrayView elements={elements} onSort={onSort}/>
  );
}

But, If I change my code a little bit It works correctly:

import React, {useState} from "react";
import ArrayView from "../ArrayView/ArrayView";

function BubbleSort({ array }) {
  const events = [];
  const [elements, setElements] = useState(array);

  const onSort = () => {
    console.log('onSort fired')
    const length = elements.length;
    const newElements = elements.slice();

    let swap = 0;

    for (let i = 0; i < length; i++) {
      for (let j = i + 1; j < length; j++) {
        if (newElements[i].value > newElements[j].value) {
          console.log('Swap fired', swap);

          const buffer = newElements[i];
          newElements[i] = newElements[j];
          newElements[j] = buffer;

          swap++

          events.push(newElements.slice());
        }
      }
    }

    for (let i = 0; i < events.length; i++) {
      setTimeout(() => setElements(events[i]), 1000 * i);
    }
  }

  return (
    <ArrayView elements={elements} onSort={onSort}/>
  );
}

export default BubbleSort;

In fact, this is exactly the same code. Why does it happen?

Edit zealous-darwin-trcvr

Answer

setTimeout is non-blocking.

In your first code example, you set a timeout after each step of the sorting process. However, that doesn’t cause the code to pause and wait, it schedules the callback to occur later. So your code continues and performs the next step of the sort, and then schedules another callback, and so on. After 1 second has passed, the callbacks fire, but the array has already finished being sorted, so the UI changes to a fully sorted array.

In your second example, you store the steps and space the timeouts to fire appropriately. The callbacks don’t look at the global state of the array, they look at each event and play them back as expected.

EDIT: Addressing your comments.

You are correct that calling slice creates a copy of the array. The problem is that you are calling slice after the callback is scheduled.

When you create an arrow function, the variables from its scope are captured, but the code inside is not evaluated until the function is called. In this case, 1 second will go by and then it will call newElements.slice() and pass that to setElements. At that point, newElements has already been sorted and all your copies will look the same.

You can solve that in two ways. The first is to do what you mentioned in the comments. Personally, I find that hard to read. The other way is to call slice immediately and use that value in the callback.

const newElementsCopy = newElements.slice();
setTimeout(() => setElements(newElementsCopy), 1000 * swap);
We are here to answer your question about Why does the sorting finish instantly? - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji