enable react-leaflet to use be usable offline
Asked Answered
S

3

6

I have been using the react-leaflet library, so far it worked well.

Now I wanted the site to pre-load as much of the tiles as possible so that the web-app(also a PWA) could be used w/o internet.

I found some existing solutions(although not dedicated for react)

This is what i've tried so far - using leaflet-offline

import React from 'react';
import 'leaflet-offline';

import {
  Map as LeafletMap,
  TileLayer,
  CircleMarker,
  Marker,
  Popup,
} from 'react-leaflet';

import 'leaflet/dist/leaflet.css';
import L from 'leaflet';
import localforage from 'localforage';

const defaultCoords = {
  latitude: 0,
  longitude: 0,
};

export class MapPage extends React.Component {
  constructor(props) {
    super(props);
    this.map = React.createRef();
  }
  componentDidMount() {
    const map = L.map('map');
    const offlineLayer = L.tileLayer.offline(
      'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
      localforage,
      {
        attribution:
          '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
        minZoom: 5,
        maxZoom: 20,
        crossOrigin: true,
      },
    );
    // offlineLayer.addTo(this.map); // tried to add to the reference, didn't work
    offlineLayer.addTo(map);
  }
  render() {
    const { latitude, longitude } = this.props.coords || defaultCoords;
    return (
      <LeafletMap
        center={this.props.initialLocation}
        zoom={16}
        // ref={this.map} // tried referencing it also, didn't work
        id="map"
      >
        <TileLayer
          attribution="&copy; <a href=&quot;https://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
          url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
        />
        <CircleMarker center={[latitude, longitude]}>
          <Popup>You are here!</Popup>
        </CircleMarker>
        <Marker
          icon={markerIcon}
          position={newPerson.location || this.props.initialLocation}
          draggable
          onDragEnd={this.props.handleNewPersonPositionChange}
        />
      </LeafletMap>
    );
  }
}

There error on this example says that, map is already initialized

Map container is already initialized.

Is there a way to make one existing solution play well with react-leaflet? Or are there better ways to add offline mode for the PWA?

Any insight would be highly appreciated. Thanks in advance!

Stacistacia answered 15/10, 2018 at 5:47 Comment(1)
Does this answer your question? Using leaflet.offline with React?Lymphoblast
C
1

Yeah you'll need to extend react-leaflet's TileLayer class. If you're using V1 that's pretty straightforward. Here's a fiddle: https://jsfiddle.net/q2v7t59h/1965/ Currently it's breaking on the localforage usage (never used that before) so you'll have to fix that. But the crux of defining a createLeafletElement function is still correct.

If you're using react-leaflet V2 then extending TileLayer is a bit more of a pain. Read through https://github.com/PaulLeCam/react-leaflet/issues/506 and you should be able to figure it out. Oh and vote for that issue if you think it deserves attention.

Claudioclaudius answered 16/10, 2018 at 13:49 Comment(3)
have you found any solution for using leaflet-offline with react-leaflet v2 ?Renarenado
I get the following error with the OfflineTileLayer class: Uncaught TypeError: Super expression must either be null or a functionBouleversement
@Bouleversement That error sounds like you’re trying to extend a react-leaflet compnent that is not extendable. You could try using my fork ‘react-leaflet-extendable’ but I haven’t updated that in a few years so you might need to rebase it off of react-leaflet.Claudioclaudius
N
-1

Add map.remove() prior to offlineLayer.addTo(map)

Nik answered 13/5, 2021 at 16:50 Comment(0)
F
-2

you can add another div with some id above leaflet

and add to map using that id ie. const map = L.map('map-id'); instead of const map = L.map('map'); in componentDidMount

Fireproofing answered 4/7, 2019 at 6:9 Comment(1)
Could you edit your answer with proper format for code blocks.Rozalin

© 2022 - 2024 — McMap. All rights reserved.