I'm trying to make D3 update an SVG element once a second by passing a fresh Date object into the data() function, followed by join() to update the page. I'm actually doing this in an Observable notebook using Promises.tick() but I think the code below (full source) is a rough approximation of the relevant bits. My end goal is to make a clock but the code here is a minimal demo of the issue I have.
The problem with this code is that the update function in join() is never called -- every time around the loop the enter function is called instead, which results in a fresh text being appended each time. Since I have one datum and one element I would expect join's update to be called, not enter. I am aware that the key function on data() (example) is significant in determining what has changed but my understanding is that the default key is the array index, which should always be 0 here. At any rate, specifying a different key function (ranging from the identity function to returning a constant) hasn't helped.
while (true) {
var data = [new Date()];
svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.selectAll("text")
.data(data)
.join(
enter => enter.append("text").text(d => "enter: " + d),
update => update.text(d => "update: " + d)
);
await new Promise(resolve => setTimeout(resolve, 1000));
}