title: D3 tooltip not updating correctly in a React Component
body: <p>I spent quite a while making this code snippet to highlight a very frustrating issue I've run into using d3 and react together, in particular with trying to dynamically update tooltips based on component state.</p>
  
  <p>First, the code snippet, which I've tried my best to keep short and complete (for brevity, you can skip over the css. just note the radio button group, and the mouseover in the graph component):</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="true">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>class GraphComponent extends React.Component {
  
    constructor(props) { 
      super(props);
    }
  
    // Lifecycle Components
    drawGraph() {
      const { buttonName } = this.props;
      
      const myData = [
        {x:25, y:30, name:"tommy", age:"24"},
        {x:108, y:82, name:"joey", age:"21"},
        {x:92, y:107, name:"nicky", age:"23"},
        {x:185, y:50, name:"peter", age:"27"},
        {x:65, y:80, name:"mickie", age:"4"},
        {x:165, y:80, name:"gregie", age:"14"},
        {x:154, y:10, name:"tammie", age:"24"},
        {x:102, y:42, name:"benny", age:"29"}
      ]
  
      // var myD3tip = d3Tip()
      var myD3tip = d3.tip()
     .attr('class', 'd3-tip')
     .offset([-20,0])
     .html(d =&gt; `&lt;p&gt;D3 Tip: ${buttonName}: ${d[buttonName]}&lt;/p&gt;`)
  
      console.log('buttonName outside mouseover', buttonName)
      const divToolTip = d3.select('div#myTooltip')
      const points = d3.select('#mySvg').select('g.points')
      points.call(myD3tip)
      points
        .selectAll('circle')
        .data(myData)
        .enter()
        .append('circle')
        .attr('cx', d =&gt; d.x)
        .attr('cy', d =&gt; d.y)
        .attr('r', 8)
        .attr('fill', 'blue')
        .on('mouseover', function(d) {
          myD3tip.show(d)
          console.log('buttonName in mouseover', buttonName)
          divToolTip
            .style('opacity', 1)
            .style('left', d3.mouse(this)[0] + 'px')
            .style('top', (d3.mouse(this)[1]) + 'px')
            .html(`&lt;p&gt;Div Tip: ${buttonName}: ${d[buttonName]}&lt;/p&gt;`)
        })
        .on('mouseout', function(d) {
          myD3tip.hide(d)
          divToolTip
            .style('opacity', 0)
        })
    }
   componentDidUpdate() {
      this.drawGraph()
    }
    componentDidMount() {
      this.drawGraph()
    }
    
   render() {
     return (
        &lt;svg id="mySvg"&gt;
          &lt;g className="points" /&gt;
        &lt;/svg&gt;
    )
   }
  }
  
  class GraphContainer extends React.Component {
  
   constructor(props) { 
    super(props);
      this.state = {
        ageOrName: "age"
      }
      
      this.handleChange = this.handleChange.bind(this);
   }
  
    handleChange = (event) =&gt; {
      this.setState({ ageOrName: event.target.value })
    }
     
   render() {
      
      const { ageOrName } = this.state;
      
      const ageOrNameOptions = ["age", "name"];
      const ageOrNameButtons = 
            &lt;form&gt;
              &lt;div&gt;
                {ageOrNameOptions.map((d, i) =&gt; {
                  return (
                    &lt;label key={i+d}&gt;
                      &lt;input 
                        type={"radio"}
                        value={ageOrNameOptions[i]}
                        checked={ageOrName === ageOrNameOptions[i]}
                        onChange={this.handleChange}
                        /&gt;
                      &lt;span&gt;{ageOrNameOptions[i]}&lt;/span&gt;
                    &lt;/label&gt;
                  )
                })}
              &lt;/div&gt;
            &lt;/form&gt;;
      
     return (
     &lt;div&gt;
           {ageOrNameButtons}
          
           &lt;GraphComponent
             buttonName={ageOrName}
           /&gt;
        &lt;/div&gt;
    )
   }
  }
  
  
  ReactDOM.render(
    &lt;GraphContainer /&gt;,
    document.getElementById('root')
  );</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>/* Div ToolTip */
  #myTooltip {
   opacity: 0;
   position: absolute;
   pointer-events: none;
   background-color: lightblue;
  
   line-height: 0.50;
   font-weight: bold;
   padding: 8px 8px;
   padding-bottom: 0px;
   border-radius: 10px;
   border: 2px solid #444;
   font-size: 0.9em;
  }
  /* ========== */
  
  
  
  /* D3 ToolTip */
  /* ========== */
  .d3-tip {
    line-height: 0.50;
    font-weight: bold;
    padding: 8px 8px;
    padding-bottom: 0px;
    border-radius: 10px;
    border: 2px solid #444;
    font-size: 0.9em;
  }
  
  /* Creates a small triangle extender for the tooltip */
  .d3-tip:after {
    box-sizing: border-box;
    display: inline;
    font-size: 10px;
    width: 100%;
    line-height: 1;
    color: #444;
    content: "\25BC";
    position: absolute;
    text-align: center;
  }
  
  /* Style northward tooltips differently */
  .d3-tip.n:after {
    margin: -1px 0 0 0;
    top: 100%;
    left: 0;
  }
  /* ========== */</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.development.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.development.js"&gt;&lt;/script&gt;
  &lt;script src="https://d3js.org/d3.v4.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.8.0-alpha.1/d3-tip.js"&gt;&lt;/script&gt;
  
  &lt;div id="root"&gt; 
    &lt;svg id="mySvg"&gt;
  &lt;/div&gt;
  &lt;div id="myTooltip"&gt;&lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>The overview is this: </p>
  
  <p>I have 2 components, a container component and a graph component. The container component has ageOrName state, and a radio button with "age" and "name" that updates this state. The container component then passes this value into the graph component. </p>
  
  <p>The graph component, receiving ageOrName as a prop, uses this prop to change the text in the tooltip. However, <strong>its not working</strong>. For absolute completeness, I've included <strong>2!</strong> different tooltips:</p>
  
  <ul>
  <li>a tooltip created with the d3-tip library</li>
  <li>a custom tooltip, created from a div on the page</li>
  </ul>
  
  <p>I have two console.logs() to display the value of the ageOrName prop inside of the graph component, and I've realized something <em>very concerning</em>. The value of the prop <strong>is different</strong> depending on whether I am inside of the "on.mouseover" call. I have no idea why.</p>
  
  <p>Getting this to work is important for an app of mine, and any help at all with this is greatly appreciated! </p>
  
  <p>Edit: Will almost certainly bounty this question in 2 days (would like to now). Will award even if an answer is provided sooner.</p>