Zoom: D3 owns the gesture, React owns the picture
Scroll over the chart to zoom and drag to move: the axis labels change because React re-renders with a new rescaled scale. D3 added only listeners. The clip path hides the line outside the plot area.
Some D3 helpers must write into the page: axes, brushes, zoom and transitions. Give each one an element that React renders empty, hand it over through a ref, run it in an effect, and always return a cleanup. Then StrictMode's double effect is harmless.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 5 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write an Axis component for a bottom axis that takes a scale prop, calls d3.axisBottom in an effect, and leaves the <g> empty again on cleanup. Why does it list [scale] as its dependency?
A teammate's Brush component adds d3.brushX() to a <g> in an effect and never removes it. Describe two problems this causes, and fix the effect.
Explain it without notes
Why does React's StrictMode run effects twice, and what kind of bug does that expose in a D3 chart?
What is the difference between selection.call(axis) and selection.append("g").call(axis) inside an effect?
Which part of a zoomable chart should live in React state, and why derive the scale instead of changing it?
When is it better to draw the axis as JSX than with d3.axisBottom?
Preview
Console
Nothing logged yet.Expected console output
whole year, x axis: 2025, April, July, October
zoomed 4x, x axis: April, May, June