0

I have a problem updating the DOM elements in D3 in a React Component. I have a component which gets data from a Slider in the main App.

The slider filters the data, removing or adding elements. When adding elements into the data the React app does not update immediately. The data is updated and loaded but the DOM is not complete.

I have boiled the issue down to this piece of code:

  useEffect (() => { 
      const mappedData = data.map(d => d.nodes).reduce((acc, nodes) => acc.concat(nodes), []);
     
      svg = d3.select(chartRef.current)

      groupSmall.current = svg.selectAll('.child').data(mappedData)


     console.log(groupSmall.current._groups); // ** THIS GIVES ODD RESULTS **

     // Enter   
      groupSmall.current
          .enter()
          .append('g')
          .attr('class', 'child')
          .attr('gx', d => d.gx)
          .attr('gy', d => d.gy)


      // Update existing and entered large groups
      groupSmall.current 
          .attr('gx', d => d.gx)
          .attr('gy', d => d.gy)


      // Remove exit large groups
      groupSmall.current.exit().remove();

    }, [data]) ; 

The console.log ( ) produces incomplete results for example:

Array [ (17) […] ]
​
0: Array(17) [ g.child, g.child, g.child
, … ]
​​
0: <g class="child">​​
1: <g class="child">​​
2: <g class="child">​​
3: <g class="child">​​
4: <g class="child">​​
5: <g class="child">​​
6: <g class="child">​​
7: <g class="child">​​
8: <g class="child">​​
9: <g class="child">​​
10: <g class="child">

Which logs an array of 17 items -but is only populated with 11. I would like D3 to fully updated BEFORE it draws the items (I have other elements to add such as forces).

Note: this DOES work if I click the slider a 2nd time : i.e trigger a 'second' update of the data..

I have tried using SetTimeOut ( ) to console.log the DOM elements to see if they would be updated after a pause.. I expected to see the the fully updated DOM but this did not work.

I think this is a fundemental issue of timing of updates between D3 and React. I am new to React so just have a basic understanding.

1
  • Try to log after groupSmall.current.exit().remove(); which modify groupSmall.current by removing dom elements not matching your data
    – pernifloss
    Commented Aug 16, 2023 at 8:26

0

Browse other questions tagged or ask your own question.