Search code examples
javascriptreactjsleafletgeojsonreact-leaflet

Using Geojson with tons of data in react leaflet


I'm using GeoJson of react-leaflet to display all polygons of an area. However, when the amount of data increase to 10000, the performance turns bad and my app has performance issues, cause it slow and laggy. How can I improve GeoJSon's performance on big data? My code :

 <Header />
      <MapContainer center={[10.7743, 106.6669]} zoom={5}>
        <TileLayer
          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        <GeoJSON
          style={LayerStyle}
          data={polygonData.features}
          onEachFeature={onEachContry}
        />
      </MapContainer>

The data of polygonData.features is very big, it has 100k records


Solution

  • You can try converting your big geojson into topojson. Because

    topojson eliminates redundancy, allowing related geometries to be stored efficiently in the same file

    as mentioned here, you can achieve significant smaller file size and thus better performance when you render it on your leaflet map.

    You can use this site to convert your huge geojson(17.1mb) to topojson(2.7mb). You can see the difference in size after converting it. Note that it does not have unlimited free conversion capability.

    After that you can create your own react wrapper to render a topojson. For this purpose you can use Vadim's answer on this stackoverflow post. It needs some adaptation to be compatible with react-leaflet v.3.x, and be able to add popups in each prefecture for instance, but after making some small changes you are able to visualize your huge geojson in topojson as it was a normal geojson.

    function TopoJSON(props) {
      const layerRef = useRef(null);
      const { data, ...otherProps } = props;
    
      function addData(layer, jsonData) {
        if (jsonData.type === "Topology") {
          for (let key in jsonData.objects) {
            let geojson = topojson.feature(jsonData, jsonData.objects[key]);
            layer.addData(geojson);
          }
        } else {
          layer.addData(jsonData);
        }
      }
    
      function onEachFeature(feature, layer) {
        if (feature.properties) {
          const { VARNAME_3, NAME_0 } = feature.properties;
          layer.bindPopup(`${VARNAME_3}, ${NAME_0}`);
        }
      }
    
      useEffect(() => {
        const layer = layerRef.current;
        addData(layer, props.data);
      }, [props.data]);
    
      return (
        <GeoJSON ref={layerRef} {...otherProps} onEachFeature={onEachFeature} />
      );
    }
    

    and use it like this:

    import topojson from "./phuong.json";
    
     <MapContainer ..>
          ...
         <TopoJSON data={topojson} />
      </MapContainer>
    

    Demo