React: d3.event es nulo en un componente ReactJS + d3JS

Creado en 28 abr. 2016  ·  3Comentarios  ·  Fuente: facebook/react

Estoy usando ReactJS, d3JS y ES6 para crear un organigrama. Puedo crear el gráfico y verlo. Pero quiero agregar el comportamiento de zoom y arrastre al gráfico, así que usé d3.behavior.zoom . Puedo ver el método ampliada que se llama, pero el d3.event es nulo.

Intenté adjuntar el comportamiento de zoom a div, svg y g, pero nada ayuda. Se llama al comportamiento ampliado pero el evento es nulo.

En mi proyecto ASP.NET, me aseguré de no tener ninguna referencia a d3.js más que en la configuración systemJS que muchas respuestas de stackoverflow mencionaron como el problema relacionado con por qué d3.event es nulo.

Mi código es muy similar al de un ejemplo como este https://github.com/Swizec/candidate-bucket-chart/blob/169779e110c8825f4545c71ae5845ff7bad4f1f4/src/BubbleChart.jsx que usa la versión anterior de ReactJS.

Esta es mi configuración systemJS:

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

Comentario más útil

Es muy probable que esté usando Babel, que tiene problemas para importar un campo mutable desde d3 usando la sintaxis de importación / exportación.

Vea esto: https://github.com/d3/d3/issues/2733#issuecomment -190743489

Querrá cambiar la forma en que importa d3 con lo siguiente:

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

Y reemplace todas las apariciones de d3.event con currentEvent .

Esto soluciona el problema con d3.js v3.

Todos 3 comentarios

El código al que hace referencia parece ser javascript d3 general, y el evento no pasa por el sistema de eventos de React. Esto parece una pregunta d3, no relacionada con React. Por esta razón, voy a cerrar este tema.

En otra nota, debe usar ref para hacer referencia a un nodo DOM, NO seleccionar por ID. El uso de elementos como d3.select("#viewport") puede causar problemas de interoperabilidad con otros componentes que eligen el mismo ID y evitar que un componente se use varias veces en la misma página. El uso de ref resolverá estos problemas.

Otros con este problema seguramente terminarán aquí, así que aquí hay un enfoque que funcionó para mí:

  1. Abra el panel de fuentes del depurador (chrome)
  2. Establecer un punto de interrupción del detector de eventos para el evento que causa el problema
  3. Recrear el problema
  4. La ejecución debería entrar en depuración. Da un paso adelante hasta que estés en d3 (particularmente d3_selection_onListener (listener, argumentz)).
  5. Ingrese a la consola y guarde una referencia global al objeto d3:

> window.theD3versionHostingTheEvent = d3;

  1. Avanza hasta listener.apply(this, argumentz); y luego elige Pasar a la siguiente llamada de función hasta que llegues al lugar donde se produce el error.
  2. Ir a la consola de nuevo y hacer: window.theD3versionHostingTheEvent == d3

Si el resultado es false , definitivamente está ejecutando dos instancias de d3. En mi caso, resultó que una de las librerías que estaba usando tenía d3 incluido.

Es muy probable que esté usando Babel, que tiene problemas para importar un campo mutable desde d3 usando la sintaxis de importación / exportación.

Vea esto: https://github.com/d3/d3/issues/2733#issuecomment -190743489

Querrá cambiar la forma en que importa d3 con lo siguiente:

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

Y reemplace todas las apariciones de d3.event con currentEvent .

Esto soluciona el problema con d3.js v3.

¿Fue útil esta página
0 / 5 - 0 calificaciones