Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setState in a onTick event that ticks every millisecond

I'm trying to set a state in an onTick event for a clock.

 <Viewer>
   <Clock
        startTime={start.clone()}
        stopTime={stop.clone()}
        currentTime={start.clone()}
        multiplier={50}
        onTick={_.throttle(handleValue, 1000)} // this thing ticks every millisecond
      />
    <Entity
          ref={ref} // here is the ref to get the value I want to set state with
          position={positionProperty}
          tracked
          selected
          model={{ uri: model, minimumPixelSize: 100, maximumScale: 100.0 }}
          availability={
            new TimeIntervalCollection([
              new TimeInterval({ start: start, stop: stop }),
            ])
          }
        />
 </Viewer>

Here is the handleValue function.

  const handleValue = (clock) => {
//setting the state here ( I want to display the chaning the value over time) 
  setHeadingValue(ref.current.cesiumElement._properties._heading.getValue(clock.currentTime));
    }
  };

The problem is it looks like it tries to re-render over and over which freezes the app. Due to the nature of setState, this behavior makes sense. But I feel like there is an answer that's escaping me. May I have some insight as to what I could do? I'm out of ideas. I'm using Resium ( a react library) and right now I'm setting the value using .getElementByID() and appending to the dom.. which defeats using react in the first place...

Here is a code sandbox: https://codesandbox.io/s/resium-cesium-context-forked-bpjuw?file=/src/ViewerComponent.js

Some elements are not showing because we need a token, but that does not affect the functionality I'm looking for. Just open the console of the code sandbox and go to the ViewerComponent.js

thank you for your help

like image 428
Esther Cuan Avatar asked May 09 '21 04:05

Esther Cuan


1 Answers

As I see, the problem here not in the library, but in a way of managing calculation and visualization.

As few people already mentioned, for UI, user don't need more than 60fps, but for process sometimes we need more.

So the solution is to separate processing from visualization.

To be more generic, here is an example in pure JavaScript:

// Here it may be some component 
const clockView = document.getElementById('speedyClock')

let state = null
// This function mimicking dispatch on state update 
function setState(val) {
  state = val
  clockView.innerHTML = state
} 

const FPS = 30


// Any state out of visualization scope
// Not the React state!!!
let history = []

let nextUiUpdate = Date.now()+(1000/FPS) 

/// Super speedy process
setInterval(function() {
  history.push(Math.random())
  const now = Date.now()
  
  // Update according to visual frame rate
  if(now >= nextUiUpdate) {
    // Prepare visual updates
    setState(JSON.stringify({count: history.length, history}, null, 2))
    history = []    
    nextUiUpdate = Date.now()+(1000/FPS)
  }
}, 1)
<pre id="speedyClock"></pre>
like image 112
Oleg Imanilov Avatar answered Sep 29 '22 02:09

Oleg Imanilov