How-to Use D3 in Next.js

I implemened a version of Kerry Rodden's awesome Sequences Sunburst in Next.js. You can see my version's code here.

The visualization is done with D3. It took some time to figure out how to get the library to work properly in Next.js. In the interest of sharing, here's how to do it.

The Specifics

  1. After creating your basic Next.js app, install D3 with:
    npm install d3
  2. Next, create a file at components/D3Example.js and paste this into it:
    import { useEffect, createRef } from 'react'
    import * as d3 from 'd3'
    
    export default function D3Example({ width, height }) {
      const ref = createRef()
    
      useEffect(() => {
        draw()
      })
    
      const draw = () => {
        const svg = d3.select(ref.current)
        svg.selectAll('*').remove()
        svg
          .append('circle')
          .attr('r', 80)
          .attr('cx', 100)
          .attr('cy', 100)
          .attr('fill', 'green')
      }
    
      return <svg width={width} height={height} ref={ref} />
    }
    
  3. Then, create a file at pages/d3-example.js with :
    import D3Example from '../components/D3Example'
    
    export default function Page() {
      return (
        <div>
          <D3Example width="200" height="200" />
        </div>
      )
    }
    
  4. And, that's it. If you fire up your site and visit the /d3-example page you'll see a green circle like this one. The D3 equivelent of Hello, World.

More Details

  • This example loads the entire D3 library via:
    import * as d3 from 'd3'
    It's possible to import only the parts you need with individual modules like:
    import { scaleLinear } from "d3-scale"
    Using the individual modules is probably the way to go for production. I'm not sure where the best place to get a list of the modules is, but you find them along with the rest of the D3 project here
  • All the createRef and useEffect stuff is designed to prevent the SVG from reloading if the comopnent updates
  • The svg.selectAll('*').remove() line prevents issues with re-appending elemnts to the SVG when the page hot-reloads during development. While it's not needed for prod it won't have any real effect so I leave it in
  • This setup does the D3 rendering on the client side. It looks like d3-node is the way to go for server-side, but I haven't messed with that yet
  • Lots of the D3 examples I've found are for older versions that aren't compatible with what gets installed from npm by default. If you have problems getting something to work, figuring out if there's a version conflict is a good first step

Send Off

This is another case of something that took a long time to find and refine that ended up being a relatively small amount of code. That happens. Hopefully this saves you that time and lets you get on to building your actual thing.

Happy coding,

- a