2016-07-12 8 views
0

このコンポーネントは、ページビューの一部として作成され、ユーザーは最初のダッシュボードからナビゲートします。 svgが正しくレンダリングする必要があるすべてのデータが正しくロギングされているように見えますが、SVGはこのビューの初期ナビゲーションでは作成されていません。関数は実行されていますが、htmlにはSVGは表示されません。最初は画像がまだロードされていなかったためだと思っていましたが、SVGが画像に直接ではなくdivに追加されているので、htmlから幅と高さを引いた値になると思います。どんな助けでも大歓迎です。d3 svgが初期コンポーネントレンダリングでレンダリングされません。 React

import React, { Component, PropTypes } from 'react'; 
import $ from 'jquery'; 
import { connect } from 'react-redux'; 

class BrainComponent extends Component { 
    static propTypes = { 
    showBrainData: PropTypes.bool.isRequired, 
    showThisHitData: PropTypes.object, 
    hit: PropTypes.object 
}; 

constructor(props, context) { 
    super(props, context); 
    this.state = { 
     showBrainData: this.props.showBrainData, 
    }; 
} 

componentWillMount() { 
    console.log(this.props); 
} 

handleBrainVizColor() { 
    console.log(this.props.hit.Hic); 
    let colorString; 
    const hic = this.props.hit.Hic; 
    const redNum = 80 + (Math.round(hic/2)); 
    const greeNum = 180 - (Math.round(hic/2)); 
    colorString = "rgba(" + redNum + "," + greeNum + ", 0, .4)"; 
    return colorString; 
} 

renderBrainViz() { 
    console.log(this.props.hit); 
    this.renderRecangles(); 
} 

componentDidMount() { 
    // this.renderBrainViz.bind(this); 
} 

renderRecangles() { 
    d3.select(".brain-canvas").remove(); 
    const fillColor = this.handleBrainVizColor(); 
    console.log(this.props.showBrainData); 
    if (this.props.showBrainData) { 
    const brainWidth = $(".brain-img").width(); 
    const brainHeight = $(".brain-img").height(); 
    let xLocation; 
    let yLocation; 
    let width = brainWidth/2; 
    let height = brainHeight/2; 
    console.log(this.props.hit.ImpactDirection); 

    switch (this.props.hit.ImpactDirection) { 
     case 'URP': 
      xLocation = brainWidth/2; 
      yLocation = 0; 
     break; 
     case 'LRP': 
      xLocation = 0; 
      yLocation = brainHeight/2; 
      height += 10; 
      break; 
     case 'CR': 
      break; 
     case 'LR': 
      xLocation = 0; 
      yLocation = 0; 
      width = brainWidth; 
      break; 
     case 'UR': 
      xLocation = 0; 
      yLocation = brainWidth/2; 
      width = brainWidth; 
      break; 
     case 'BA': 
      break; 
     case 'LF': 
      xLocation = 0; 
      yLocation = 0; 
      width = brainWidth; 
      break; 
     case 'UF': 
      xLocation = 0; 
      yLocation = 0; 
      width = brainWidth; 
      break; 
     case 'ULP': 
      xLocation = 0; 
      yLocation = 0; 
      break; 
     case 'LLP': 
      xLocation = 0; 
      yLocation = 0; 
      break; 
     } 

    const brainCanvas = d3.select(".brain-one").append("svg") 
       .attr("width", brainWidth) 
       .attr("height", brainHeight) 
       .attr("class", "brain-canvas"); 
    brainCanvas.append("rect") 
      .attr("x", xLocation) 
      .attr("y", yLocation) 
      .attr("width", width) 
      .attr("height", height) 
      .style("fill", fillColor); 
    } 
} 

render() { 
     return (
      <div className="brain-container"> 
       <div className="brain-one"> 
        <img className="brain-img" src="https://s3-us-west-2.amazonaws.com/mvtrak/new-brain.png" /> 
       </div> 
       { this.renderBrainViz() } 
       { !this.props.showBrainData ? <div> 
       <div className="brain-overlay"></div> 
       <div className="select-hit-text">SELECT HIT BELOW</div> 
       </div> : null } 
      </div> 
    ); 
} 
} 

function mapStateToProps(state) { 
    console.log(state); 
    return { 
     hit: state.hitData 
    }; 
} 

export default connect(mapStateToProps)(BrainComponent); 

答えて

2

それはあなたが見せているようrender()内に作成されたDOM要素がまだその時点でDOM要素をシャドウしているため、render()内からthis.renderBrainViz()を呼び出すことは不適切です。彼らはrender()が実行された後にのみ実際のDOM要素になり、Reactはそれらの影DOM要素を実際のDOMにdiffして実現することを行います。それが存在しないため、

d3.select(".brain-one").append("svg") 

はまだ選択するには、no .brain-oneを持っていません。つまり、初めてrender()は、順番にthis.renderBrainViz()呼び出す、このラインと呼ばれています。

render()への2回目の呼び出しで動作します。この時点では、最初の呼び出しですでに.brain-oneが存在していますが、それは幸運なことです。私はまだそれを同期外と考えています。

適切な方法は、決してrender()内からthis.renderRectangles()を呼び出していないし、代わりにあなたがたがコメントアウトしていたとしてもcomponentDidMount()componentDidUpdate()内からそれを呼び出すことです。 (.bind()を使用する必要はありません)。 renderRectangles()内からd3.select(".brain-one")を呼び出すためにOKかもしれませんが、複数のBrainComponent Sが存在するならば、そこに複数の.brain-oneだろうとd3は遭遇した最初のものを選択することになるので、

また、それは、問題になることでしょう。より良い方法は.brain-oneへの参照を設定するのリアクトref機能を使用することです:

<div className="brain-one" ref="brainOne"> 

その方法は、あなたが最後に

d3.select(this.refs.brainOne).append("svg") 

ような何かを行うことができますが、それはrenderRectangles()内、おそらくに良いアイデアではありません常に削除して再作成してください。.brain-canvas代わりに、それを削除して、それが存在しない場合は条件付きでのみ作成するべきではありません。

if(d3.select(this.refs.brainOne).select('.brain-canvas').empty()) { 
    // means it doesn't exist 
} 

それとも、あなたは以下を使用して、それが既に存在しているかどうかに応じて、サイズ1または0の.enter()セットを返しますトリックのようなものを使用することができます:

.brain-canvasは次のように存在するかどうかを確認することができます
d3.select(this.refs.brainOne).selectAll('.brain-canvas') 
    .data([null]) // bind to a data array of 1 element 
.enter() 
    .append('svg') // will only append the svg if it doesn't exist yet 
    .attr('class', 'brain-canvas') 
    .... 
+1

これは驚くほど役に立ち、すべてが意味をなさないものです。 – hifilorau

関連する問題