React: d3.event adalah null dalam komponen ReactJS + d3JS

Dibuat pada 28 Apr 2016  ·  3Komentar  ·  Sumber: facebook/react

Saya menggunakan ReactJS, d3JS dan ES6 untuk membuat bagan organisasi. Saya dapat membuat bagan dan melihatnya. Tapi saya ingin menambahkan perilaku zoom dan drag ke grafik, jadi saya menggunakan d3.behavior.zoom . Saya dapat melihat metode yang diperbesar dipanggil, tetapi d3.event adalah nol.

Saya mencoba melampirkan perilaku zoom ke div, svg dan g tetapi tidak ada yang membantu. Perilaku yang diperbesar dipanggil tetapi acaranya nol.

Dalam proyek ASP.NET saya, saya memastikan bahwa saya tidak memiliki referensi ke d3.js selain dalam konfigurasi systemJS yang banyak jawaban stackoverflow disebutkan sebagai masalah yang terkait dengan mengapa d3.event adalah nol.

Kode saya sangat mirip dengan apa yang ada dalam contoh seperti ini https://github.com/Swizec/candidate-bucket-chart/blob/169779e110c8825f4545c71ae5845ff7bad4f1f4/src/BubbleChart.jsx yang menggunakan ReactJS versi lama.

Ini adalah konfigurasi systemJS saya:

<script>
    System.defaultJSExtensions = true;
    System.config({
        map: {
            'rx': "https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.all.min.js",
            'react': 'https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react.js',
            'react-dom': 'https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-dom.js',
            'd3': 'https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.js'
        }
    });
    System.import('../app/app.js');
</script>
import React, { Component } from 'react';
import * as Rx from 'rx';
import * as d3 from 'd3';
import Person from './person';

class OrgChart extends Component {

    constructor(props) {
        super(props);

        this.state = { persons: [] };
    }

    componentWillMount() {
        // Just read a JSON file
        var source = Rx.Observable.fromPromise($.getJSON("/js/org-persons.json"));

        source.subscribe(
            function(chart) {
                var tree = d3.layout.tree()
                    .nodeSize([110, 50])
                    .separation(function() {
                        return 1;
                    });

                var nodes = tree.nodes(chart[0]).reverse();

                var links = tree.links(nodes);

                var p = [];

                nodes.forEach(function(node) {
                    fs.push((<Person x={node.x} y={node.y}></Person>));
                }.bind(this));

                this.setState({ person: p });

            }.bind(this)
        );
    }

    componentDidMount() {
        var rootX = document.body.clientWidth / 4;
        var rootY = 300;

       // A standard setup with d3 to use it's zoom/drag behavior
        var zoom = d3.behavior.zoom()
            .scaleExtent([1, 10])
            .on("zoom", this.zoomed)
            .translate([rootX, rootY]);

       // Attach zoom behavior to the first group in the svg.
        d3.select("#viewport")
            .call(zoom);
    }

    // When I drag the svg, this function gets called but the event is null. d3 is a global object.
    zoomed() {
        d3.select("#viewport").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
    }

   // renders an org chart
    render() {

        return (
            <div id='treeContainer'><svg id='fullTree' width='100%'>
                <g id='viewport'>
                    { this.state.persons }
                </g>
            </svg></div>
        );
    }
}

export default OrgChart;

Komentar yang paling membantu

Kemungkinan besar Anda menggunakan Babel, yang mengalami masalah saat mengimpor bidang yang dapat diubah dari d3 menggunakan sintaks impor/ekspor.

Lihat ini: https://github.com/d3/d3/issues/2733#issuecomment -190743489

Anda ingin mengubah cara Anda mengimpor d3 dengan yang berikut:

import * as d3 from 'd3';
import {event as currentEvent} from 'd3';

Dan ganti semua kemunculan d3.event dengan currentEvent .

Ini memperbaiki masalah dengan d3.js v3.

Semua 3 komentar

Kode yang Anda rujuk tampaknya merupakan javascript d3 umum, dan acara tersebut tidak melewati sistem acara React. Ini terlihat seperti pertanyaan d3, tidak terkait dengan Bereaksi. Untuk alasan ini, saya akan menutup masalah ini.

Pada catatan lain, Anda harus menggunakan ref untuk mereferensikan simpul DOM, BUKAN memilih berdasarkan ID. Menggunakan hal-hal seperti d3.select("#viewport") dapat menyebabkan masalah interoperabilitas dengan komponen lain yang kebetulan memilih ID yang sama, dan mencegah komponen digunakan beberapa kali pada halaman yang sama. Menggunakan ref akan menyelesaikan masalah ini.

Orang lain dengan masalah ini pasti akan berakhir di sini, jadi inilah pendekatan yang berhasil untuk saya:

  1. Buka panel sumber debugger (chrome)
  2. Tetapkan breakpoint pendengar acara untuk acara yang menyebabkan masalah
  3. Buat ulang masalah
  4. Eksekusi harus masuk ke debug. Langkah maju sampai Anda berada di d3 (khususnya d3_selection_onListener(listener, argumentz)).
  5. Masuk ke konsol dan simpan referensi global ke objek d3:

> window.theD3versionHostingTheEvent = d3;

  1. Langkah maju sampai listener.apply(this, argumentz); dan kemudian pilih Langkah ke panggilan fungsi berikutnya sampai Anda sampai ke tempat melempar kesalahan.
  2. Masuk ke konsol lagi, dan lakukan: window.theD3versionHostingTheEvent == d3

Jika hasilnya false , Anda pasti menjalankan dua instance d3. Dalam kasus saya, ternyata salah satu lib yang saya gunakan memiliki d3 yang dibundel ke dalamnya.

Kemungkinan besar Anda menggunakan Babel, yang mengalami masalah saat mengimpor bidang yang dapat diubah dari d3 menggunakan sintaks impor/ekspor.

Lihat ini: https://github.com/d3/d3/issues/2733#issuecomment -190743489

Anda ingin mengubah cara Anda mengimpor d3 dengan yang berikut:

import * as d3 from 'd3';
import {event as currentEvent} from 'd3';

Dan ganti semua kemunculan d3.event dengan currentEvent .

Ini memperbaiki masalah dengan d3.js v3.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat