I am learning react by working on a sorting algorithm visualizer and I want to update the state array that is rendered, regularly in a loop.
Currently I am passed an array with pairs of values, first indicating the current index and value, and second with its sorted index and value.
[(firstIdx, value), (sortedIdx, value), (secondIdx, value), (sortedIdx, value) ... etc]
some actual values:
`[[1, 133], [0, 133], [2, 441], [2, 441], [3, 13], [0, 13] ... ]`
What I want to do is cut the value out of the array, splice it into the correct position, while updating the state array rendered in each step. effectively creating an animation with the state array.
Right now when I run below function, my state array instantly becomes the sorted array because of the batching. I would like there to be a delay between each state update in the loop.
code snippet that I've tried.
insertionSort(changeArray) {
const arrayBars = document.getElementsByClassName('array-bar')
// I want to keep track which index to move from/to so I instantiate it outside the loop.
let [barOneIdx, barOneValue] = [0, 0];
let [barTwoIdx, barTwoValue] = [0, 0];
// Copy of the state array that I will modify before setting the state array to this.
let auxArray = this.state.array.slice();
for (let i = 0; i < changeArray.length; i++) {
// This tells me whether it is the first or second pair of values.
let isFirstPair = 1 % 2 !== 1;
if (isFirstPair) {
// first set of values is the current index + height
[barOneIdx, barOneValue] = changeArray[i];
// Changes the current bar to green.
setTimeout(() => {
arrayBars[barOneIdx].style.backgroundColor = 'green';
}, i * 300);
} else {
// second set of values is the sorted index + height.
[barTwoIdx, barTowValue] = changeArray[i];
// Cut the current bar out of the array.
let cutIdx = auxArray[barOneIdx];
auxArray.splice(barOneIdx, 1);
// Splice it into the sorted index
auxArray.splice(barTwoIdx, 0, cutIdx);
// Changes the color of the bar at the correct sorted
// index once, and then again to revert the color.
setTimeout(() => {
// Set the state array with the new array. NOT WORKING
// Instantly sets state array to final sorted array.
// I want this to run here with a delay between each loop iteration.
this.setState({ array: auxArray });
arrayBars[barTwoIdx].style.backgroundColor = SECONDARY_COLOR;
}, i * 300);
setTimeout(() => {
arrayBars[barTwoIdx].style.backgroundColor = PRIMARY_COLOR;
}, i * 300);
}
}
}
https://codesandbox.io/s/eager-yonath-xpgjl?file=/src/SortingVisualizer/SortingVisualizer.jsx
link to my project so far with all the relevant functions and files.
On other threads say not to use setState
in a loop as they will be batched and run at the end of the block code. Their solutions won't work for my project though as I want to create an animation with the state array.
What would be the best way to implement this?