Angelos Orfanakos

EsriTileLayer component for React Leaflet

React Leaflet is a React library that exposes Leaflet classes as React components, making it very easy to add interactive maps to React web apps.

This is the fifth in a series of posts on how I use the library. My intention is to share back some of the things I’ve learned and implemented in the hope of them being useful to others.

In this post, I present the EsriTileLayer component which exposes Esri tile layers by wrapping esri-leaflet as a React component.

First, the component:

import { createLayerComponent } from '@react-leaflet/core';
import * as L from 'leaflet';
import * as esri from 'esri-leaflet';
import PropTypes from 'prop-types';

const createEsriTileLayer = (props = {}, context) => {
  const imagery = esri.tiledMapLayer({    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer',
    ...props
  });
  const labels = esri.tiledMapLayer({    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer',
    ...props
  });
  const group = L.layerGroup([imagery, labels]);
  return { instance: group, context };
};

const EsriTileLayer = createLayerComponent(createEsriTileLayer, () => null);

export default EsriTileLayer;

Things to note:

  • Line 7: Satellite imagery tile layer
  • Line 11: Place labels overlay tile layer
  • Line 15: Both layers are combined into a single one
  • Line 6, 9, 13: Any props passed to the component (e.g. token) are forwarded to each tile layer

And here’s how you’d use it in a map:

import React from 'react';

import EsriTileLayer from './EsriTileLayer';
// import EsriTileLayer from './EsriTileLayerWrapper';

const GREECE_BOUNDS = [
  [31.08, 14.26],
  [44.91, 34.69],
];

function MyMap() {
  return (
    <MapContainer
      bounds={GREECE_BOUNDS}
      style={{ width: '100%', height: '100vh' }}
    >
      <EsriTileLayer />
    </MapContainer>
  );
}

export default MyMap;

Since esri-leaflet is supposed to be used in the browser and breaks with frameworks that perform SSR like Gatsby, I had to wrap it in the following component to make it work with gatsby build:

import React, { useState, useEffect } from 'react';

const EsriTileLayerWrapper = (props) => {
  const [Component, setComponent] = useState(null);

  useEffect(() => {
    import('./EsriTileLayer').then(mod => {
      setComponent(() => mod.default);
    });
  }, []);

  return Component ? <Component {...props} /> : null;
}

export default EsriTileLayerWrapper;

To use this component, you simply replace EsriTileLayer with EsriTileLayerWrapper.