React asynchronously rendering multiple components with states

297 Views Asked by At

I'm trying to make use of GPU.js in a sample CRA React project. I'm trying to make a visible comparison between CPU & GPU calculations, but React "waits" for CPU calculations to finish before showing all results, despite them being in separate components, using separate states.

Example: In the same component

function Combined() {
  const [gpu, setGpu] = useState('null')
  const [cpu, setCpu] = useState('null')

  useEffect(() => {
    const size = 500
    const matrices = generateMatrices(size)
    setGpu(gpuMultiplyMatrix(matrices, size))
    setCpu(cpuMultiplyMatrix(matrices, size))
  }, [])

  return (
    <div className='App'>
      ...
      <div>{gpu && gpu}</div>
      <div>{cpu && cpu}</div>
      ...
    </div>
  )
}

In the same component, React will wait for cpuMultiplyMatrix to finish before rendering the component. I expected this.

View GIF

Example: Separated components

GPU

function GPUOnly() {
  const [gpu, setGpu] = useState('null')

  useEffect(() => {
    const size = 500
    const matrices = generateMatrices(size)
    gpuMultiplyMatrixAsync(matrices, size).then(result => setGpu(result))
  }, [])

  return (
    <div className='App'>
      GPU in separated Component
      <div>{gpu && gpu}</div>
      <hr />
    </div>
  )
}

CPU

function CPUOnly() {
  const [cpu, setCpu] = useState('null')

  useEffect(() => {
    const size = 500
    const matrices = generateMatrices(size)
    cpuMultiplyMatrixAsync(matrices, size).then(result => setCpu(result))
  }, [])

  return (
    <div className='App'>
      CPU in separated Component
      <div>{cpu && cpu}</div>
      <hr />
    </div>
  )
}

App

import GPUOnly from './components/GPU'
import CPUOnly from './components/CPU'

function App() {
  return (
    <>
      <GPUOnly />
      <CPUOnly />
    </>
  )
}

Despite being separated, React still waits for the CPU calc to finish before it can render the GPU, even though the GPU component finished tasks must faster.

View GIF

I've tried asynchronous calls, & separating them into their own hooks. No changes as useEffect performs the functions within it's callback synchronously.

How can I achieve asynchronous behaviour when rendering multiple components?

1

There are 1 best solutions below

0
On BEST ANSWER

IF the async calls are run on a background thread (e.g. a web worker), then it should work as intended, i.e. the components should finish and render independently. Just because the API is async doesn't necessarily guarantee they run in the background.

A toy example shows the behaviour you are looking for does work on React, in the way you describe: https://codesandbox.io/s/cool-pond-s2u1z?file=/src/App.js