2016-07-12 6 views
0

Diese Komponente wird als Teil einer Seitenansicht erstellt, in der Benutzer zu dem ursprünglichen Dashboard navigieren. Alle Daten, die vom SVG korrekt gerendert werden müssen, scheinen korrekt zu loggen, aber das SVG wird gerade nicht bei der anfänglichen Navigation zu dieser Ansicht erstellt. Die Funktion läuft, aber kein SVG wird im HTML angezeigt. Zuerst dachte ich, es war, weil das Bild noch nicht geladen wurde, aber das SVG wird an das Div nicht direkt an das Bild angehängt, so würde es zumindest ich denke, in der HTML-Minus-Breite und Höhe zeigen. Jede Hilfe würde sehr geschätzt werden.d3 Svg wird beim Rendern der ersten Komponente nicht gerendert. Reagieren

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

Antwort

2

Es ist unangemessen this.renderBrainViz() von innen render() zu nennen, wie Sie zeigen, weil die DOM-Elemente innerhalb render() erstellt werden noch an diesem Punkt DOM-Elemente Schatten. Sie werden erst zu echten DOM-Elementen, nachdem render() fertig ist und React seine Sache zum Diff macht und diese Schatten-DOM-Elemente in echtes DOM umsetzt. Mit anderen Worten wird das erste Mal render() genannt, die wiederum ruft this.renderBrainViz(), diese Zeile:

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

keine .brain-one hat noch zu wählen, weil es nicht existiert.

Es funktioniert auf den 2. Anruf zu render(), weil an diesem Punkt .brain-one existiert bereits vom ersten Anruf, aber das ist ein glücklicher Zufall. Ich würde es immer noch als nicht synchron ansehen.

Der richtige Weg ist nie this.renderRectangles() aus render() anrufen und es stattdessen aus componentDidUpdate() anrufen und auch innerhalb componentDidMount() wie Sie aber heraus kommentiert hatte. (Mit .bind() ist dort nicht notwendig).

Auch, obwohl es in Ordnung sein könnte d3.select(".brain-one") aus renderRectangles() zu nennen, wäre es ein Problem sein, wenn es mehrere BrainComponent s existiert, denn dann gäbe es mehrere .brain-one und d3 wählen begegnet die erste wäre. Eine bessere Art der Reaktion ref Funktion nutzen zu können ist eine Referenz auf .brain-one einzustellen:

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

Auf diese Weise Sie so etwas wie

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

Schließlich tun können, ist es wahrscheinlich keine gute Idee zu sein, innerhalb renderRectangles() immer entfernen und neu erstellen .brain-canvas. Stattdessen sollten Sie es niemals entfernen und nur bedingt erstellen, wenn es nicht existiert. Sie können überprüfen, ob .brain-canvas wie folgt vorhanden:

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

Oder Sie können eine Art Trick verwenden, die eine .enter() Menge der Größe 1 oder 0 zurückkehren wird, je nachdem, ob es bereits vorhanden ist, mit dem folgenden:

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

Dies ist erstaunlich hilfreich und macht jede Menge Sinn. – hifilorau

Verwandte Themen