I'm building a component to test the performance of different algorithms. The algorithms return the ms they took to run and this is want I want to display. The "fastAlgorithm" takes about half a second, and the "slowAlgorithm" takes around 5 seconds.
My problem is that the UI is not re-rendered with the result until both algorithms have finished. I would like to display the result for the fast algorithm as soon as it finishes, and the slow algorithm when that one finishes.
I've read about how React batches updates before re-rendering, but is there someway to change this behavior? Or is there a better way to organize my component/s to achieve what I want?
I'm using react 16.13.1
Here is my component:
import { useState } from 'react'
import { fastAlgorithm, slowAlgorithm } from '../utils/algorithms'
const PerformanceTest = () => {
const [slowResult, setSlowResult] = useState(false)
const [fastResult, setFastResult] = useState(false)
const testPerformance = async () => {
fastAlgorithm().then(result => {
setFastResult(result)
})
slowAlgorithm().then(result => {
setSlowResult(result)
})
}
return (
<div>
<button onClick={testPerformance}>Run test!</button>
<div>{fastResult}</div>
<div>{slowResult}</div>
</div>
)
}
export default PerformanceTest
I read somewhere that ReactDOM.flushSync() would trigger the re-rendering on each state change, but it did not make any difference. This is what I tried:
const testPerformance = async () => {
ReactDOM.flushSync(() =>
fastAlgorithm().then(result => {
setFastResult(result)
})
)
ReactDOM.flushSync(() =>
slowAlgorithm().then(result => {
setSlowResult(result)
})
)
}
And also this:
const testPerformance = async () => {
fastAlgorithm().then(result => {
ReactDOM.flushSync(() =>
setFastResult(result)
)
})
slowAlgorithm().then(result => {
ReactDOM.flushSync(() =>
setSlowResult(result)
)
})
}
I also tried restructuring the algorithms so they didn't use Promises and tried this, with no luck:
const testPerformance = () => {
setFastResult(fastAlgorithm())
setSlowResult(slowAlgorithm())
}
Edit
As Sujoy Saha suggested in a comment below, I replaced my algorithms with simple ones using setTimeout(), and everything works as expected. "Fast" is displayed first and then two seconds later "Slow" is displayed.
However, if I do something like the code below it doesn't work. Both "Fast" and "Slow" shows up when the slower function finishes... Does anyone know exactly when/how the batch rendering in React happens, and how to avoid it?
export const slowAlgorithm = () => {
return new Promise((resolve, reject) => {
const array = []
for(let i = 0; i < 9000; i++) {
for(let y = 0; y < 9000; y++) {
array.push(y);
}
}
resolve('slow')
})
}