簡體   English   中英

React-Three-Renderer引用在componentDidUpdate中不最新(包括MVCE)

[英]React-Three-Renderer refs not current in componentDidUpdate (MVCE included)

我正在使用react-three-renderer( npmgithub )與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進行一些日志記錄。 這是我遇到的問題的核心。 第一次單擊切換按鈕后,我希望形狀的參考指向圓形。 但是從日志中可以看到,在componentDidUpdate ,引用仍然指向該框:

componentDidUpdate:活動形狀為方框

登錄后顯示引用回調已命中

box ref null [在舊ref上調用null以防止內存泄漏]

圓參考[object Object]

您可以放入斷點以進行驗證和檢查。 在我們進入componentDidUpdate之前,我希望這兩件事會發生,但是正如您所看到的,這是相反的。 為什么是這樣? react-three-renderer是否存在潛在問題(如果可以,您是否可以診斷出來?),或者我誤解了React refs?

MVCE在此github存儲庫中可用。 下載它,運行npm install ,然后打開_dev / public / home.html。

提前致謝。

我在react-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方法繪制畫布,並且不會填充子代或調用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. 這將繪制出一個畫布的react-three-renderer渲染器。
  3. 調用App組件的componentDidUpdate。
  4. 調用react-three-renderer的componentDidUpdate。
  5. 這將調用_render方法。
  6. _render方法通過將props.children(網格對象)傳遞給Three庫來更新畫布。
  7. 安裝網格對象時,將調用相應的引用。

這解釋了您在控制台語句中觀察到的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM