gpt4 book ai didi

javascript - React-Three-Renderer 引用在 componentDidUpdate 中不是当前的(包括 MVCE)

转载 作者:数据小太阳 更新时间:2023-10-29 04:19:06 30 4
gpt4 key购买 nike

我正在使用 react-three-renderer ( npm , github ) 来构建带有 three.js 的场景.

我遇到了一个归结为 MVCE 的问题。引用没有按我期望的顺序更新。首先,这里是要查看的主要代码:

var React = require('react');
var React3 = require('react-three-renderer');
var THREE = require('three');
var ReactDOM = require('react-dom');

class Simple extends React.Component {
constructor(props, context) {
super(props, context);

// construct the position vector here, because if we use 'new' within render,
// React will think that things have changed when they have not.
this.cameraPosition = new THREE.Vector3(0, 0, 5);

this.state = {
shape: 'box'
};

this.toggleShape = this.toggleShape.bind(this);
}

toggleShape() {
if(this.state.shape === 'box') {
this.setState({ shape: 'circle' });
} else {
this.setState({ shape: 'box' });
}
}

renderShape() {
if(this.state.shape === 'box') {
return <mesh>
<boxGeometry
width={1}
height={1}
depth={1}
name='box'
ref={
(shape) => {
this.shape = shape;
console.log('box ref ' + shape);
}
}
/>
<meshBasicMaterial
color={0x00ff00}
/>
</mesh>;
} else {
return <mesh>
<circleGeometry
radius={2}
segments={50}
name='circle'
ref={
(shape) => {
this.shape = shape;
console.log('circle ref ' + shape);
}
}
/>
<meshBasicMaterial
color={0x0000ff}
/>
</mesh>
}
}

componentDidUpdate() {
console.log('componentDidUpdate: the active shape is ' + this.shape.name);
}

render() {
const width = window.innerWidth; // canvas width
const height = window.innerHeight; // canvas height

var position = new THREE.Vector3(0, 0, 10);
var scale = new THREE.Vector3(100,50,1);

var shape = this.renderShape();

return (<div>
<button onClick={this.toggleShape}>Toggle Shape</button>
<React3
mainCamera="camera"
width={width}
height={height}
onAnimate={this._onAnimate}>
<scene>
<perspectiveCamera
name="camera"
fov={75}
aspect={width / height}
near={0.1}
far={1000}
position={this.cameraPosition}/>
{shape}
</scene>
</React3>
</div>);
}
}

ReactDOM.render(<Simple/>, document.querySelector('.root-anchor'));

这会渲染一个带有绿色框的基本场景,这是 react-three-renderer 的 github 登陆页面上示例的一个分支。左上角的按钮将场景中的形状切换为蓝色圆圈,如果再次单击,则返回绿色框。我正在 ref 回调和 componentDidUpdate 中做一些记录。这是我遇到的问题的核心所在。第一次单击切换按钮后,我希望形状的 ref 指向圆圈。但是正如您从日志中看到的那样,在 componentDidUpdate 中,ref 仍然指向该框:

componentDidUpdate: the active shape is box

在那之后登录行显示 ref 回调被命中

box ref null [React calls null on the old ref to prevent memory leaks]

circle ref [object Object]

您可以放置​​断点来验证和检查。我希望这两件事在我们进入 componentDidUpdate 之前发生,但正如您所见,它是相反发生的。为什么是这样? react-three-renderer 中是否存在潜在问题(如果是,您能诊断出来吗?),还是我误解了 React refs?

MVCE 在 this github repository 中可用.下载它,运行 npm install,然后打开 _dev/public/home.html。

提前致谢。

最佳答案

我查看了react-three-renderer中的源码。在 lib/React3.jsx 中,有一个两阶段渲染。

componentDidMount() {
this.react3Renderer = new React3Renderer();
this._render();
}

componentDidUpdate() {
this._render();
}

_render 方法似乎是加载子项的方法 - Three 中的网格对象。

_render() {
const canvas = this._canvas;

const propsToClone = { ...this.props };

delete propsToClone.canvasStyle;

this.react3Renderer.render(
<react3
{...propsToClone}
onRecreateCanvas={this._onRecreateCanvas}
>
{this.props.children}
</react3>, canvas);
}

render 方法绘制 Canvas 并且不填充子项或调用 Three。

  render() {
const {
canvasKey,
} = this.state;

return (<canvas
ref={this._canvasRef}
key={canvasKey}
width={this.props.width}
height={this.props.height}
style={{
...this.props.canvasStyle,
width: this.props.width,
height: this.props.height,
}}
/>);
}

总结一下,这是顺序:

  1. 调用应用组件渲染。
  2. 这会渲染绘制 Canvas 的 react-three-renderer。
  3. App组件的componentDidUpdate被调用。
  4. 调用react-three-renderer的componentDidUpdate。
  5. 这会调用 _render 方法。
  6. _render 方法通过将 props.children(网格对象)传递给 Three 库来更新 Canvas 。
  7. 安装网格对象时,将调用相应的引用。

这解释了您在控制台语句中观察到的内容。

关于javascript - React-Three-Renderer 引用在 componentDidUpdate 中不是当前的(包括 MVCE),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39626921/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com