如何在每毫秒滴答一次的 onTick 事件中设置状态
How to setState in a onTick event that ticks every millisecond
我正在尝试在时钟的 onTick 事件中设置状态。
<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>
这里是 handleValue 函数。
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));
}
};
问题是它似乎试图一遍又一遍地重新呈现,这会冻结应用程序。
由于 setState 的性质,这种行为是有道理的。但我觉得有一个答案在逃避我。
我可以对我能做什么有所了解吗?我没主意了。
我正在使用 Resium(一个反应库),现在我正在使用 .getElementByID()
设置值并附加到 dom.. 首先使用反应失败...
这是一个代码沙箱:https://codesandbox.io/s/resium-cesium-context-forked-bpjuw?file=/src/ViewerComponent.js
有些元素没有显示,因为我们需要一个令牌,但这不会影响我正在寻找的功能。只需打开代码沙箱的控制台并转到 ViewerComponent.js
感谢您的帮助
据我所知,这里的问题不在库中,而是在管理计算和可视化的方式中。
正如少数人已经提到的,对于 UI,用户不需要超过 60fps,但对于处理有时我们需要更多。
所以解决方案是将处理与可视化分开。
为了更通用,这里有一个纯 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>
我建议使用 requestAnimationFrame
,而不是 setInterval
,因为它们没有必要在每次屏幕刷新时多次重新渲染 React 树。
通过结合使用 shouldComponentUpdate
和 setState
,您可以有效地 setState
并防止不必要的渲染。
This is my codesandbox url to show it.
您可以随时访问您想要的值,但我们需要使用 shouldComponentUpdate
函数防止每毫秒渲染 1 次。
我正在尝试在时钟的 onTick 事件中设置状态。
<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>
这里是 handleValue 函数。
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));
}
};
问题是它似乎试图一遍又一遍地重新呈现,这会冻结应用程序。
由于 setState 的性质,这种行为是有道理的。但我觉得有一个答案在逃避我。
我可以对我能做什么有所了解吗?我没主意了。
我正在使用 Resium(一个反应库),现在我正在使用 .getElementByID()
设置值并附加到 dom.. 首先使用反应失败...
这是一个代码沙箱:https://codesandbox.io/s/resium-cesium-context-forked-bpjuw?file=/src/ViewerComponent.js
有些元素没有显示,因为我们需要一个令牌,但这不会影响我正在寻找的功能。只需打开代码沙箱的控制台并转到 ViewerComponent.js
感谢您的帮助
据我所知,这里的问题不在库中,而是在管理计算和可视化的方式中。
正如少数人已经提到的,对于 UI,用户不需要超过 60fps,但对于处理有时我们需要更多。
所以解决方案是将处理与可视化分开。
为了更通用,这里有一个纯 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>
我建议使用 requestAnimationFrame
,而不是 setInterval
,因为它们没有必要在每次屏幕刷新时多次重新渲染 React 树。
通过结合使用 shouldComponentUpdate
和 setState
,您可以有效地 setState
并防止不必要的渲染。
This is my codesandbox url to show it.
您可以随时访问您想要的值,但我们需要使用 shouldComponentUpdate
函数防止每毫秒渲染 1 次。