How to import and use D3-tube-map in react.js

Viewed 871

I have imported tube-map from d3.js in my reactjs project. But getting the following issue for not importing it properly. The issue I'm getting is shown in below sceenshot:

enter image description here

Following is the code I'm using. I've installed d3-tube-map using npm. Maybe I'm lacking on properly importing the exported value of d3-tube-map. Any help about this issue?

import React, { Component } from "react";
// import d3 from "d3";
import d3 from "d3-tube-map";
import "d3-tip";
import tubeData from "./JSON/tube_data.jsx";

class TubeMap extends Component {
    componentDidMount() {
        var container = d3.select("#tube_map_101");
        var width = 700;
        var height = 400;

        var map = d3
            .tubeMap()
            .width(width)
            .height(height)
            .margin({
                top: 20,
                right: 20,
                bottom: 40,
                left: 100
            })
            .on("click", function(name) {
                console.log(name);
            });

        // d3.json("./stations.json", function (error, data) {
        container.datum(tubeData).call(map);

        var svg = container.select("svg");

        zoom = d3
            .zoom()
            .scaleExtent([0.5, 6])
            .on("zoom", zoomed);

        var zoomContainer = svg.call(zoom);
        var initialScale = 2;
        var initialTranslate = [100, 200];

        zoom.scaleTo(zoomContainer, initialScale);
        zoom.translateTo(
            zoomContainer,
            initialTranslate[0],
            initialTranslate[1]
        );

        function zoomed() {
            svg.select("g").attr("transform", d3.event.transform.toString());
        }
        // });
    }

    render() {
        return <div id="tube_map_101" />;
    }
}

export default TubeMap;
2 Answers

Yes, your imports aren't quite right. If you look at the example provided on the npm page for this module, it uses both d3 and d3-tube-map.

<script src="https://d3js.org/d3.v4.js"></script>
<script src="../dist/d3-tube-map.js"></script>

Which gives a clue, but doesn't help much with how to do this using ES6 imports. Looking at the code for the module over on github, I would try this first (many lines excluded):

import tubeMap from "d3-tube-map";

...

    var map = tubeMap() 

What I noticed on github is that the tubeMap module already imports d3 inside it. So maybe you don't need to import d3 yourself.

If the above doesn't work, you may have to import both d3 and d3-tube-map, in which case I'm not sure how they should work together as imports. If that's the case, I would open an issue on github with the author to get an example.

EDIT: As it turns out, you need to import all the compononents from each module per the code snippet below.

import * as d3 from "d3";
import * as tubeMap from "d3-tube-map";
import tubeData from "./data/tubeData.jsx";

class TubeMap extends Component {
    componentDidMount () {
      d3.tubeMap = tubeMap.tubeMap
      this.renderMap()
    }


    renderMap() {
        var container = d3.select("#tube_map_101");
        var width = 700;
        var height = 400;

        var map = d3
            .tubeMap()
            .width(width)
            .height(height)

etc.

With latest version of d3 and d3-tube-map none of the answer works. I tried everything.

The solution (workaround) is following

import React, { Component } from 'react';
import tubeData from './data';
import './TubeMap.css';

const d3 = require('d3');
const tubeMap = require('d3-tube-map');

export default class TubeMap extends Component {

    componentDidMount() {
        d3.tubeMap = tubeMap.tubeMap;
        d3.select('#tube-map').html(null);

        this.renderMap();
    }
    renderMap() {

        var container = d3.select('#tube-map');
        var width = 700;
        var height = 700;

        var map = d3.tubeMap()
            .width(width)
            .height(height)
            .margin({
                top: 20,
                right: 20,
                bottom: 40,
                left: 100,
            })
            .on("click", function (name) {
                console.log(name);
            });


        container.datum(tubeData).call(map);
    }


    render() {
        return (
            <div id="tube-map"></div>
        )
    }
}

Notes

  1. Don't import d3 or d3-tubemap (d3-tip is also useless in this case)
  2. Initialize d3 and d3-tubemap with require
  3. Add tubeMap to d3 in componentDidMount. I am clearing html because the componentDidMount is called twice
Related