reactjsreact-leafletreact-leaflet-v3

Updating the Chloropleth Tutorial to react-leaflet v3 With Function React Components


I was wondering if anyone knew how to update this tutorial (https://leafletjs.com/examples/choropleth/) to work with react-leaflet v3 as well as react function components. The parts I can't get working is resetting the GeoJSON style when you mouse off a layer as well as zooming into the layer whenever you click on it. Here is the code I have now (I am not too worried about the actual coloring portion of the tutorial right now). Also, I am not very good with react or JS in general so if you see any bad practices please point them out to me! Thanks!

import '../App.css';
import caMapData from '../data/caProvince.json'
import mxMapData from '../data/mxStates.json'
import usMapData from '../data/usStates.json'

import {MapContainer, TileLayer, Marker, Popup, GeoJSON} from 'react-leaflet'

function MainMap() {
  const geoStyleCA = {
    fillColor: 'white',
    weight: 2,
    opacity: 1,
    color: 'red',
    dashArray: '3',
    fillOpacity: 0.5
  }

  const geoStyleUS = {
    fillColor: 'white',
    weight: 2,
    opacity: 1,
    color: 'blue',
    dashArray: '3',
    fillOpacity: 0.5
  }

  const geoStyleMX = {
    fillColor: 'white',
    weight: 2,
    opacity: 1,
    color: 'green',
    dashArray: '3',
    fillOpacity: 0.5
  }

  const onEachFeature = ((feature, layer) => {
    layer.on({
      mouseover: highlightFeature,
      mouseout: resetHighlight,
      click: zoomToFeature
    });
  })

  const highlightFeature = ((e) => {
    e.target.bringToFront();
    e.target.setStyle({
      weight: 5,
      color: '#666',
      dashArray: '',
      fillOpacity: 0.7
    });
  })

  const resetHighlight = ((e) => {
    // update this to work with react-leaflet 3 and functional react components
    e.target.resetStyle();
  })

  const zoomToFeature = ((e) => {
    // update this to work with react-leaflet 3 and functional react components
    e.fitBounds(e.target.getBounds());
  })

  return(
    <MapContainer
      center={[44.967243, -103.771556]}
      zoom={4}
      scrollWheelZoom={true}>
      <TileLayer
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <Marker position={[44.967243, -103.771556]}>
        <Popup>
          Middle of US.
        </Popup>
      </Marker>
      <GeoJSON data={caMapData.features} style={geoStyleCA}/>
      <GeoJSON data={usMapData.features} style={geoStyleUS} onEachFeature={onEachFeature}/>
      <GeoJSON data={mxMapData.features} style={geoStyleMX}/>
    </MapContainer>
  );
}

export default MainMap;

Solution

  • fitBounds is meant to be called on the leaflet map, not on target:

    import { ... useMap } from 'react-leaflet';
    
    const map = useMap();
    const zoomToFeature = ((e) => {
      // update this to work with react-leaflet 3 and functional react components
      map.fitBounds(e.target.getBounds());
    })
    

    resetStyle is mean to be called on the GeoJSON object:

      const onEachFeature = ((feature, layer) => {
        layer.on({
          mouseover: highlightFeature,
          mouseout: () => resetHighlight(layer),
          click: zoomToFeature
        });
      })
    
      const resetHighlight = ((layer) => {
        // update this to work with react-leaflet 3 and functional react components
        layer.resetStyle();
      })
    
    

    Overall, your code is very clean for someone new to JS. Well done.