D3.js Enter, Update, Exit — The Data Join Pattern
In this tutorial, you will learn about D3.js Enter, Update, Exit. We cover key concepts, practical examples, and best practices to help you master this topic.
D3.js enter-update-exit pattern binds data arrays to DOM selections, creating elements for new data, updating existing ones, and removing elements for data that no longer exists.
What You'll Learn
By the end of this guide, you will use the data join pattern, implement enter-update-exit lifecycle, use key functions for stable identity tracking, merge enter and update selections, and build dynamic visualizations that respond to data changes.
Why the Pattern Matters
Static charts are easy. Dynamic charts that respond to changing data are the real challenge. In Durga Antivirus Pro, the real-time threat dashboard uses enter-update-exit to add new threat nodes, update existing ones, and remove resolved threats — all with smooth transitions.
flowchart TD
A[Data Array] --> B[.data(data)]
B --> C{Match Elements?}
C -->|New| D[ENTER - .append]
C -->|Existing| E[UPDATE - .attr]
C -->|Extra| F[EXIT - .remove]
D --> G[.merge]
E --> G
G --> H[All Elements Updated]
Basic Data Join
var data = [10, 20, 30, 40, 50];
var selection = d3.select('#list')
.selectAll('li')
.data(data);
// ENTER: create <li> for each new data item
selection.enter()
.append('li')
.text(function(d) { return d; });
Full Enter-Update-Exit Pattern
function render(data) {
var items = d3.select('#list')
.selectAll('li')
.data(data);
// EXIT: remove elements with no data
items.exit().remove();
// ENTER: create elements for new data
var enter = items.enter()
.append('li');
// ENTER + UPDATE: merge and update all
enter.merge(items)
.text(function(d) { return 'Value: ' + d; })
.style('color', function(d) {
return d > 30 ? 'green' : 'orange';
});
}
Using Key Functions
var data = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
var selection = d3.select('#list')
.selectAll('li')
.data(data, function(d) { return d.id; });
// With key function, elements track by identity, not index
// If data order changes, elements follow their data
Why keys: Without keys, D3 matches by index. If you remove item 0, the element at index 0 gets the new data instead of being removed.
Animated Transitions
items.exit()
.transition()
.duration(300)
.style('opacity', 0)
.remove();
enter.append('li')
.style('opacity', 0)
.transition()
.duration(300)
.style('opacity', 1);
enter.merge(items)
.transition()
.duration(300)
.text(function(d) { return d; });
Common Mistakes
1. Forgetting to Call .enter()
Data bound to an empty selection does nothing without .enter().append().
2. Not Calling .exit().remove()
Old elements stay in the DOM when data shrinks. Always call exit().remove().
3. Calling .data() Without Re-selecting
The data join works on the current selection. If the DOM already has elements, selectAll must include them.
4. Ignoring Key Functions for Dynamic Data
Without key functions, adding or removing items causes incorrect element reuse.
5. Merging Without Understanding
enter.merge(items) combines both selections. Operations after merge apply to both new and existing elements.
Practice Questions
Q1: What happens if you call .data() on a selection of 5 elements with an array of 3 items? A: 3 items go to enter-update, 2 elements go to exit (no matching data).
Q2: Why would you use a key function with .data()? A: To track elements by identity instead of index. Elements follow their data when order changes.
Q3: What does .exit() return? A: A selection of DOM elements that have no corresponding data in the bound array.
Q4: What is the merge method used for? A: It combines enter and update selections so you can apply the same operations to both.
Q5: How do you animate exit elements out?
A: Call .transition().duration(300).style('opacity', 0).remove() on the exit selection.
Challenge: Build a live data dashboard that adds a random data point every second, keeps a maximum of 20 points, and removes oldest points with a fade animation.
FAQ
Try It Yourself
Build a dynamic bar chart that updates every second, adding and removing bars with smooth transitions.
<!DOCTYPE html>
<html>
<head>
<title>Enter Update Exit Demo</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.bar { fill: #4ecdc4; transition: fill 0.3s; }
.controls { margin: 10px 0; }
button { padding: 8px 16px; margin: 4px; cursor: pointer; }
</style>
</head>
<body>
<h2>Dynamic Bar Chart</h2>
<div class="controls">
<button onclick="addBar()">Add Bar</button>
<button onclick="removeBar()">Remove Last</button>
<button onclick="randomize()">Randomize</button>
</div>
<svg width="400" height="200" id="chart"></svg>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
var data = [30, 60, 90, 50, 70];
function render() {
var svg = d3.select('#chart');
var bw = 400 / Math.max(data.length, 1);
var maxVal = d3.max(data) || 1;
var bars = svg.selectAll('rect').data(data);
bars.exit()
.transition().duration(300)
.attr('height', 0).attr('y', 200)
.remove();
var enter = bars.enter()
.append('rect').attr('class', 'bar')
.attr('height', 0).attr('y', 200);
enter.merge(bars)
.transition().duration(300)
.attr('x', function(d, i) { return i * bw; })
.attr('y', function(d) { return 200 - d * 200 / maxVal; })
.attr('width', bw - 2)
.attr('height', function(d) { return d * 200 / maxVal; });
}
function addBar() { data.push(Math.floor(Math.random() * 100) + 10); render(); }
function removeBar() { if (data.length > 1) data.pop(); render(); }
function randomize() { data = data.map(function() { return Math.floor(Math.random() * 100) + 10; }); render(); }
render();
</script>
</body>
</html>
What's Next
Master D3.js transitions for animated visualizations.
Transitions — D3.js animated transitions. Axis — Creating axes in D3.js.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro