React: d3.event é nulo em um componente ReactJS + d3JS

Criado em 28 abr. 2016  ·  3Comentários  ·  Fonte: facebook/react

Estou usando ReactJS, d3JS e ES6 para criar um organograma. Posso criar o gráfico e vê-lo. Mas eu quero adicionar o zoom e o comportamento de arrastar ao gráfico, então usei d3.behavior.zoom . Posso ver que o método com zoom é chamado, mas o d3.event é nulo.

Tentei anexar o comportamento do zoom ao div, svg e g, mas nada ajudou. O comportamento ampliado é chamado, mas o evento é nulo.

Em meu projeto ASP.NET, certifiquei-me de não ter nenhuma referência a d3.js além da configuração systemJS, que muitas respostas de stackoverflow mencionaram como o problema relacionado ao motivo de d3.event ser nulo.

Meu código é muito semelhante ao que está em um exemplo como este https://github.com/Swizec/candidate-bucket-chart/blob/169779e110c8825f4545c71ae5845ff7bad4f1f4/src/BubbleChart.jsx que usa a versão antiga do ReactJS.

Esta é a minha configuração 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;

Comentários muito úteis

É muito provável que você esteja usando o Babel, que tem problemas para importar um campo mutável do d3 usando a sintaxe de importação / exportação.

Veja isto: https://github.com/d3/d3/issues/2733#issuecomment -190743489

Você vai querer alterar a maneira como importa d3 com o seguinte:

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

E substitua todas as ocorrências de d3.event por currentEvent .

Isso corrige o problema com d3.js v3.

Todos 3 comentários

O código ao qual você faz referência parece ser javascript d3 geral e o evento não passa pelo sistema de eventos do React. Parece uma questão d3, não relacionada ao React. Por esse motivo, encerrarei este problema.

Em outra nota, você deve usar um ref para fazer referência a um nó DOM, NÃO selecionando por ID. Usar coisas como d3.select("#viewport") pode causar problemas de interoperabilidade com outros componentes que escolhem o mesmo ID e evitar que um componente seja usado várias vezes na mesma página. Usar um ref resolverá esses problemas.

Outros com esse problema certamente irão parar aqui, então aqui está uma abordagem que funcionou para mim:

  1. Abra o painel de fontes do depurador (chrome)
  2. Defina um ponto de interrupção do ouvinte de evento para o evento que está causando o problema
  3. Recrie o problema
  4. A execução deve entrar em depuração. Avance até chegar ao d3 (particularmente d3_selection_onListener (listener, argumentz)).
  5. Entre no console e salve uma referência global ao objeto d3:

> window.theD3versionHostingTheEvent = d3;

  1. Avance até listener.apply(this, argumentz); e, em seguida, escolha Avançar para a próxima chamada de função até chegar ao local que gerou o erro.
  2. Entre no console novamente e faça: window.theD3versionHostingTheEvent == d3

Se o resultado for false , você definitivamente está executando duas instâncias de d3. No meu caso, descobri que uma das bibliotecas que eu estava usando tinha o d3 incluído.

É muito provável que você esteja usando o Babel, que tem problemas para importar um campo mutável do d3 usando a sintaxe de importação / exportação.

Veja isto: https://github.com/d3/d3/issues/2733#issuecomment -190743489

Você vai querer alterar a maneira como importa d3 com o seguinte:

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

E substitua todas as ocorrências de d3.event por currentEvent .

Isso corrige o problema com d3.js v3.

Esta página foi útil?
0 / 5 - 0 avaliações