Although D3.js is a powerful visualization tool, the goal of this guide is to display a map of the US using SVG and React without the need for D3.

One of the most crucial aspects of this map is a complex JSON file that describes the shape of every state. Using existing source data from bl.ocks.org user Pasha as a template, I created my own states.json file which you are free to use as you like. This entire project is modeled on the demo from Pasha.

A very simple incarnation of a React SVG map of the U.S.A. could look like this.

Demo

Note: This demo is loaded with React DOM and is not optimized for performance. See code below and this page’s source code for details

Code

I find that using React to manually generate SVG is far more readable and much simpler than the D3 jQuery-selector based API, but that’s just me!

Note that this is only using vanilla SVG and a modern React build with hooks and functional components. There is plenty of room for customization with standard event handlers and JS. No other third party libraries required!

// Normally these would be "import" statements, but this is a simple demo and
// is needed to render in the browser.
const { useEffect, useState } = React;

// Functional component for the SVG map. Take in the map JSON data as a prop and
// return SVG.
const USMap = (props) => {
  const { statesData } = props;

  return (
    <svg viewBox="0 0 960 600">
      {statesData.map((stateData, index) =>
        <path
          className="someCSSClass"
          style={{cursor: "pointer", fill: "orange"}}
          key={index}
          stroke="#fff"
          strokeWidth="6px"
          d={stateData.shape}
          onMouseOver={(event) => {
            event.target.style.fill = 'red';
          }}
          onMouseOut={(event) => {
            event.target.style.fill = 'orange';
          }}
        >
        </path>
      )}
    </svg>
  )
}

// Functional component for the app. This handles loading the data and showing
// some sort of loading UI while waiting for the data.
const App = () => {
  // The statesData is null by default until we set it.
  const [statesData, setStatesData] = useState(null);

  // This should only run once due to the [] arg for the dependencies.
  useEffect(() => {
    (async () => {
      const res = await fetch('https://willhaley.com/assets/united-states-map-react/states.json');
      const statesData = await res.json();
      // Set the statesData with the data received from fetch().
      setStatesData(statesData);
    })();
  }, []);

  // If there is no statesData yet, show a loading indicator.
  if (!statesData) {
    return (
      <div>Loading...</div>
    );
  }

  return (
    <USMap statesData={statesData} />
  );
};

// ReactDOM is used to render React in a browser directly. This is not typical
// and a "normal" React build pipeline should be used for production apps.
ReactDOM.render(
  <App />,
  document.getElementById('demo-app'),
);