I'm creating a generator function in React, to produce an insertionSort animation, step-by-step:
function* insertionSort(data) { // yield state of array at each step of sorting
const inputArr = [...data]
let n = inputArr.length
for (let i = 1; i < n; i++) {
// Choosing the first element in our unsorted subarray
let current = inputArr[i]
// The last element of our sorted subarray
let j = i - 1
while (j > -1 && current < inputArr[j]) {
inputArr[j + 1] = inputArr[j]
j--
}
inputArr[j + 1] = current
yield inputArr
}
yield inputArr
}
export default insertionSort
and calling the next() function on every button press:
<button
onClick={() => {
console.log(insertionSort(data).next().value)
}}>
Insertion Sort
</button>
However, only the first button press produces the expected results. Every subsequent press just reproduces the same thing.
I am confident the function logic is correct, as removing the generator syntax and just using it as a normal loop produces the correct results.
Am I missing something in how yield works?
Every call to insertionSort(data)
creates a new generator that starts from the beginning. You're repeatedly doing the first step on a new instance. You'll want to use
const sorter = useRef();
<button onClick={() => {
console.log(data);
sorter.current = insertSort(data);
}}>
Start Insertion Sort
</button>
<button onClick={() => {
console.log(sorter.current.next().value);
}}>
Step
</button>