D3.JS | Проблема с конфликтом выбора фильтра ReactJS «this»

#reactjs #d3.js #filter #attributes #selection

#reactjs #d3.js #Фильтр #атрибуты #выбор

Вопрос:

В необработанном JavaScript есть очень простой эскиз

    var actives = { active1: false, active2: true, active3: true, active4: false };

var svg = d3.select('body').append('svg').attr('width', 512).attr('height', 512);

var rect1 = svg.append("rect").attr("class", "boxElement active1 active2 active3").attr("x", 32).attr("y", 32).attr("width", 100).attr("height", 100).attr("fill", "#888888");

var rect2 = svg.append("rect").attr("class", "boxElement active1 active4").attr("x", 160).attr("y", 32).attr("width", 100).attr("height", 100).attr("fill", "#DDDDDD");

d3.selectAll('.boxElement').filter(function(){ var classes = d3.select(this).attr("class"); console.log(classes); var sum = false; Object.keys(actives).forEach(function(a_){ if(classes.includes(a_)){ console.log("found"); sum  = actives[a_]; }}); return sum > 0 ? true : false }).attr("fill", "#00FF00");  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>  

В этом случае console.log(d3.select(this)) возвращает классы rectangle, и это правильно. Мне нужно написать некоторую функцию (вместо d3.select(this).attr("class").includes("whatever") ) внутри фильтра, чтобы выбрать, какие прямоугольники будут голубыми на основе изменения класса.

Однако мне нужно сделать то же самое в ReactJS, и кажется, что ‘this’ зарезервировано, а filter console.log(d3.select(this)) возвращает сам компонент.

Синтаксис .filter(function(item_){ console.log(item_); return true; }) также не работает, он возвращает undefined и console.log(item_.attr("class")) возвращает ошибку.

Итак, как я могу получить доступ к каждому выбору и его атрибутам один за другим при методе фильтрации, если d3.select(this) не работает?

Комментарии:

1. codesandbox.io/s/d3-react-hooks-forked-2lihv?file=/src/index.js Нажмите на синюю кнопку.

2. Спасибо! Речь идет о коде в update() ? Как только я использую .filter(function() { console.log(this);}); вместо .filter(() => console.log(this)); , записанное значение снова становится правильным, в противном случае оно не определено.

3. codesandbox.io/s/d3-react-hooks-forked-2lihv?file=/src/index.js Мне нужно получить доступ к attr(‘class’), однако filter(() => console.log(this.attr(‘class’); ) возвращает ошибку. «это» зарезервировано родительским компонентом, и я ищу решение для доступа к каждому выбору.

Ответ №1:

Это не элегантное решение, однако оно работает. Я использую .nodes().map(...)

 import React, { useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import * as d3 from "d3";

import "./styles.css";


function App() {
  return (
    <div className="App">
      <MockupD3 id="d3svg" />
    </div>
  );
}

class MockupD3 extends React.Component {

  constructor(props_) {

    super(props_);
    this.actives = { active1: false, active2: true, active3: true, active4: false };

    this.clickMe = this.clickMe.bind(this);
  }
  clickMe(){

    let this_ = this;

    d3.selectAll('.box').nodes().map(node_ => {
      
      let sum = 0;
      Object.keys(this_.actives).forEach(key_ =>{

        let classes = node_.attributes.class.value;
        if(classes.includes(key_)){

         sum  = this_.actives[key_];

        }

      })
      if(sum > 0) { node_.attributes.fill.value = "#00FF00"; }
      else { node_.attributes.fill.value = "#FF0000"; }
    
    })

  }
  render() {
    return ( <svg id="mockup" width={512} height={512}>
      <rect class={'box active1 active2 active3'} x={64} y={64} width={64} height={64} fill={'#888888'}></rect>
      <rect class={'box active1 active4'} x={160} y={64} width={64} height={64} fill={'#222222'}></rect>
      <rect class={''} x={64} y={140} width={160} height={32} fill={'#0000FF'} onClick={this.clickMe}></rect>
    </svg> )
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
  

https://codesandbox.io/s/d3-react-hooks-forked-2lihv?file=/src/index.js:0-1411

Все еще ищу подход filter ().