I'm trying to build a sorting visualizer similar to this: https://clementmihailescu.github.io/Sorting-Visualizer/ using React.
To handle updating the Canvas with each step in the mergesort algorithm, I'm attempting to use a state variable yHeights (corresponding to the height of each line, to be sorted) and updating the state of this variable during each call to mergesort().
However, I'm running into an infinite loop, I believe because I am not keeping the render() method "pure" - as in, I am updating state during the render method.
How can I refactor this code to properly update the canvas drawing during each call of mergesort()? I think I may be able to use getDerivedStateFromProps to do this, but I'm struggling to understand and implement using the documentation.
Code:
//App.js
import logo from './logo.svg';
import './App.css';
import Controls from './Controls';
import Canvas from './Canvas';
import {useState} from 'react'
var xPositions = []
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
function App() {
const [yHeights, setyHeights] = useState([])
function merge(left, right) {
let sortedArr = []; // the sorted elements will go here
while (left.length && right.length) {
// insert the smallest element to the sortedArr
if (left[0] < right[0]) {
sortedArr.push(left.shift());
} else {
sortedArr.push(right.shift());
}
}
// use spread operator and create a new array, combining the three arrays
return [...sortedArr, ...left, ...right];
}
function mergeSort(arr) {
setyHeights([arr])
const half = arr.length / 2;
// the base case is array length <=1
if (arr.length <= 1) {
return arr;
}
const left = arr.splice(0, half); // the first half of the array
const right = arr;
return merge(mergeSort(left), mergeSort(right));
}
const draw = context => {
var arrHeights = []
context.fillStyle = "rgb(0, 0, 0)";
for (var i = 0; i < 100; i+=1) {
const height = getRandomInt(500)
context.fillRect(i * 10, 0, 10, height);
xPositions.push(i*10);
arrHeights.push(height)
}
setyHeights(arrHeights);
console.log(yHeights)
};
return (
<div className="App">
<Controls />
<Canvas draw={draw} numLines={100} />
</div>
);
}
export default App;