map.get() method isn't working with D3 v6

608 Views Asked by At

I am new to D3.js and I am trying to make some animation with my graph, but I can't resolve a problem with the .get() method called on a d3.map for D3 version 6. When I run the code it throws an error:

nodeById.get is not a function

My code is based on: https://bl.ocks.org/ctufts/bd6956a45ea69734f5909c8b526c13b5

//some fetch data in json file
d3.json("someURLjsonfile").then(function (graph) {
        
let nodes = graph.nodes,
    nodeById = d3.map(nodes, function (d) {
      return d.id;
    }),
    links = graph.links,
    bilinks = [];
            

    links.forEach(function (link) {
    var  s = nodeById.get(link.source),  // <-- error
         t = nodeById.get(link.target),  // <-- error
         i = {}; // intermediate node
         nodes.push(i);
         links.push({
                    source: s,
                    target: i
                }, {
                    source: i,
                    target: t
                });
                bilinks.push([s, i, t]);
            });
1

There are 1 best solutions below

1
altocumulus On

Your problem is caused by some rather unfortunate re-design of the API. As of D3 v6 the d3-collection module was deprecated and removed from the D3 bundle. That module contained the d3.map() constructor method that would create a d3.map object, i.e. one of D3's internal map implementations mimicking the native JavaScript Map. This method has been around a while but has lost importance once ES6 feature became available and was therefore removed.

Sadly, with version 2 of the d3-array module a method with the same name was introduced which is basically equivalent to the native array.map() or Array.from() methods:

# d3.map(iterable, mapper) · Source

Returns a new array containing the mapped values from iterable, in order, as defined by given mapper function. Equivalent to array.map and Array.from:

Since d3-array v2 was introduced to the bundle with the same version 6 that also removed d3-collection the d3.map property is still available, however, its meaning has changed.

Your code seems to have been written for D3 <v6 and breaks because of the changes laid out above. The new d3.map() is a mapper function not a constructor; it returns an array which does not feature a .get() method, hence, the error.

To fix the issue you can change your code to directly use the built-in Map object instead:

nodeById = new Map(Array.from(nodes, d => [d.id, d]));

With the rest untouched your code should be running as expected.