useState正在使用react three光纤冻结useFrame中的渲染流



我正在将我在three js中的一个项目移动到react three fiber中,并且我在渲染循环中遇到了一些问题。也许我不完全理解useFrame是如何工作的。

这是CodeSandbox:

https://codesandbox.io/s/react-three-test-y0zrx?file=/src/Three.jsx:1824-1835

因此,在这个项目中,我使用滚动来在z轴上移动相机,并更改当我们到达z位置上的不同点时显示的年份。正如您所看到的,当我们达到这一点时,我们使用useState集函数来更改状态,但也会创建滞后并暂时禁用渲染效果。

这是更改显示信息的渲染器功能(从位置开始的年份(:

ThreeComponent.jsx

const getYear = cameraZ => parseInt(cameraZ / -10 + START_YEAR, 10);
const getRoundedYear = year => Math.round(year / 10) * 10;
const shouldDisplayYear = roundedYear => {
return (
roundedYear % 100 === 0 || (roundedYear > 1890 && roundedYear % 10 === 0)
);
};
function Renderer() {
const composer = useRef();
const { scene, gl, camera } = useThree();
useFrame(() => {
const roundedYear = getRoundedYear(getYear(camera.position.z));
if (shouldDisplayYear(roundedYear)) {
// The problem lies here
setDisplayedYear(roundedYear);
}
return composer?.current?.render();
}, 1);
return (
<effectComposer ref={composer} args={[gl]}>
<renderPass attachArray="passes" scene={scene} camera={camera} />
<bokehPass
attachArray="passes"
args={[
scene,
camera,
{
focus: 20.0,
aperture: 1.1 * 0.00008,
maxblur: 0.05,
width: window.innerWidth,
height: window.innerHeight
}
]}
/>
</effectComposer>
);
}
...
return (
<div className="three-component" ref={canvasRef}>
<Canvas
...>
...
<Renderer/>
</Canvas>
</div>
);

set函数是从父组件传递的,但如果它在同一组件上,则会出现相同的问题:

ThreeComponent.jsx

const ThreeComponent = ({ setDisplayedYear, startYear }) => {

App.js(父级(

const [displayedYear, setDisplayedYear] = useState(START_YEAR);

有人能解释一下为什么会出现这种滞后吗?或者,也许有一种更好的方法来移动相机,只需滚动和更新数字。

非常感谢!

useFrame是一个渲染循环,每秒运行60次,不会有副作用。setDisplayedYear将要求react完成所有繁重的任务,困难,通过vdoms等。充其量它会坦克性能,否则它只会杀死标签。

你可以在这里做很多事情,最好的办法就是随时改变相机。你可以从useState(state=>state.camera.i会删除所有setState的东西。

编辑:

我认为,在每次渲染时,你也会在那里重新创建大量不必要的对象。例如,每次setState更改时都会创建函数Renderer((,它从头开始重新创建整个效果。组件应该始终是固定引用。

下面是一个将相机移入移出的例子:https://codesandbox.io/s/r3f-lod-rzuj1

这里有另一个可能更接近你所需要的(凸轮对滚动偏移的反应(:https://codesandbox.io/s/adoring-feather-nk16u