2016-09-21 50 views
8

我使用react-three-renderer(npmgithub)構建場景,其格式爲three.jsReact-Three-Renderer在componentDidUpdate中未引用current(包含MVCE)

我遇到了一個問題,我已經簡化爲MVCE。 Refs沒有按照我期望的順序進行更新。首先,這裏的主代碼來看看:

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')); 

這使得一個基本的場景綠色方框,示例的反應,三渲染器的GitHub的着陸頁上叉。左上角的按鈕將場景中的形狀切換爲藍色圓圈,如果再次單擊,則返回綠色框。我在ref回調中做了一些日誌記錄,並在componentDidUpdate。這就是我遇到的問題的核心所在。在第一次點擊切換按鈕之後,我希望形狀的ref指向圓圈。但你可以從記錄看,在componentDidUpdate裁判仍然指向盒子:

componentDidUpdate:主動形狀盒

登錄線,揭示了後裁判回調被擊中

框REF空[陣營呼叫空對舊REF以防止內存泄漏]

圓REF [對象的對象]

您可以放下斷點以驗證和檢查。在我們輸入componentDidUpdate之前,我會期待這兩件事情發生,但正如你所看到的,它正在發生逆轉。爲什麼是這樣?在反應三渲染器中是否存在潛在問題(如果是這樣,你能診斷它嗎?),還是我誤解React refs?

該MVCE可在this github repository。下載它,運行npm install,並打開_dev/public/home.html。

在此先感謝。

+0

我不認爲你誤解了React的參考文獻。在沒有React Three Renderer的情況下做同樣的事情會給你想要的行爲:https://jsfiddle.net/pa4nd46k/。 – tobiasandersen

回答

2

我在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方法繪製畫布,不填充子項或調用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(網格對象)傳遞給三個庫來更新畫布。
  7. 當網格對象被掛載時,調用相應的引用。

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