2

I am using the LeafletJS plugin to display a full page map in a ReactJS single page app. I followed the instructions here. However, the tiles are not displayed in correct order. They are ordered randomly (?). I found a similar problem here but in that case the order was fixed on page refresh. That is not true for me. My code is (excluding boilerplate):

index.html

<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="stylesheets/atlas.css">
  </head>
  <body>
    <div id="app">
      Loading...
    </div>
    <script src="javascripts/atlas.js"></script>
  </body>
</html>

index.js

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('app')
)

App.jsx

import LiveMap from './LiveMap';
// App component
const App = () => (
    <LiveMap />
)
export default App;

LiveMap.jsx

class LiveMap extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div id='map'></div>
        );
    }

    componentDidMount() {
        let _map = this.map = L.map(ReactDOM.findDOMNode(this)).setView([-41.2858, 174.78682], 14);
        L.tileLayer(
            'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> Contributors',
            maxZoom: 18,
            }).addTo(_map);    
    }

    componentWillUnmount() {...}

    shouldComponentUpdate() {return false;}
};
export default LiveMap;
Community
  • 1
  • 1
341008
  • 9,862
  • 11
  • 52
  • 84
  • Try setting a timeout before you render the map. `componentDidMount` can be somewhat misleading in that the element has been inserted into the DOM but not fully rendered (no width and height). Leaflet needs the width and height to render properly... – Greg Venech Apr 09 '16 at 16:03
  • What are your `atlas.css` and `atlas.js` files made of? The shuffled tiles is usually a symptom of not loading `leaflet.css` stylesheet. – ghybs Apr 09 '16 at 17:10
  • @SkipJack tried that. Didn't help. – 341008 Apr 10 '16 at 17:54
  • @ghybs I tried loading `leaflet.css` explicitly. Still no success. – 341008 Apr 10 '16 at 17:54
  • @341008 if it's not either of those things then I'm kind of at a loss.. Can you add a live example of the issue? – Greg Venech Apr 10 '16 at 18:24
  • @341008 were you able to resolve this? I'm interested as to what it ended up being... – Greg Venech May 14 '16 at 05:49
  • Have you found a solution @341008? I'm getting the same problem. – Javier Muñoz Jul 20 '16 at 06:21

1 Answers1

1

I'm pretty sure your issue is that the element has not fully rendered by the time your code executes or, as mentioned by @ghybs, not loading the Leaflet stylesheet. See this question, especially the second answer, which addresses this problem:

One drawback of using componentDidUpdate, or componentDidMount is that they are actually executed before the dom elements are done being drawn, but after they've been passed from React to the browser's DOM.

Solution

In order to get around this you must wrap your map creation code in a setTimeout like so:

componentDidMount() {
    let element = ReactDOM.findDOMNode(this)

    setTimeout(() => {
      this.map = new L.map(element, {
          center: new L.LatLng(41.019829, 28.989864),
          zoom: 14,
          maxZoom: 18,
          layers: new L.TileLayer('...')
      }, 100)
    })
  }

I put together a pen which illustrates a working example of a leaflet map inside a React component. Also make sure you are including leaflet's stylesheet:

...
<head>
  <link rel="stylesheet" href="stylesheets/atlas.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.css">
</head>
...

I would also recommend using ref which I updated the pen to use. You can read more refs here.

Related Questions

Good way to combine React and Leaflet

React after render

Community
  • 1
  • 1
Greg Venech
  • 8,062
  • 2
  • 19
  • 29
  • What you are saying definitely makes sense. And your pen obviously works. But when I try doing the same in my code it breaks. I just copied code from your pen to my (stripped down) files and got shuffled tiles as before. I must be missing something basic here. – 341008 Apr 10 '16 at 17:56
  • I also tried the trick with `window.requestAnimationFrame(callback)` mentioned in the link you pointed to. No luck. – 341008 Apr 10 '16 at 18:02
  • 2
    @341008 You're most likely missing the stylesheet then.. If you look at the codepen style settings I'm loading it there (not directly through the html section) – Greg Venech Apr 10 '16 at 18:22