reactjsgoogle-mapsgoogle-maps-api-3geojsongoogle-maps-react

Google Maps React Polygon Issues


I am creating an app that uses wildfire data from APIs and flips it in order to display polygons on a Google Map using the google-maps-react package. I have figured everything out up until returning and displaying the polygon using a function built into the map component. Does anyone want to chime in on what the issue might be? I'd really appreciate some help. Thanks.

import React, { Component } from 'react';
import { Map, GoogleApiWrapper, Polygon } from 'google-maps-react';



const mapStyles = {
    margin: 30,
    width: '93.75%',
    height: '90%',
    border: '1px solid #3E1C18',
    display: 'inline-block'
};


class FireMap extends Component {

    constructor(props) {
        super(props)

        this.state = {
            fires: [],
            polygons: []
        }
    }
    

    componentDidMount() {
        fetch('https://services3.arcgis.com/T4QMspbfLg3qTGWY/arcgis/rest/services/Public_Wildfire_Perimeters_View/FeatureServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json')
            .then(res => res.json())
            .then(data => {
                this.setState({ fires: data.features })
                this.state.fires.map((fire) =>{
                    if (fire.geometry !== null){
                        let fireCoords = fire.geometry.rings
                        let trueCoords = []
                        fireCoords.map((coords) => {
                            coords.map((pair) => {
                                let newPair = {lat: pair[1], lng: pair[0]}
                                return trueCoords.push(newPair)
                            })
                        })
                        this.state.polygons.push(trueCoords);
                        console.log(this.state.polygons)
                     }
                 })
            })
    }

    showPolygons = () => {
        this.state.polygons.map((polygon) => {
            let firePoly=  <Polygon paths={polygon} options={{
                fillColor: "#BF5E4B",
                fillOpacity: 0.45,
                strokeColor: "#6B352A",
                strokeOpacity: 0.9,
                strokeWeight: 1
            }}/>
            return firePoly
        })
    }
    
    render(){
        return(
            <div className="mapBox">
                <Map
                    google={this.props.google}
                    zoom={8}
                    style={mapStyles}
                    initialCenter={{ lat: 37.7749, lng: -122.4149 }}
                >
                    {this.showPolygons()}
                </Map>
            </div>
        );
    }
}

Solution

  • I haven't caught from your comment if you've tried things I've suggested... But you've edited your post with some random (and incorrect) changes. OK, I'll try to post an answer. It's an answer related to the original code because it looks simpler and contains less errors.

    This is how I think it should look like:

    const coord_pair_to_latlng =  ([lat,lng]) => ({ lat, lng })
    const convert_ring_coords = ring => ring.map(coord_pair_to_latlng)
    
    class FireMap extends Component {
      constructor(props) {
        super(props)
        this.state = { fires: [] }
      }
      componentDidMount() {
        fetch('https://services3.arcgis.com/T4QMspbfLg3qTGWY/arcgis/rest/services/Public_Wildfire_Perimeters_View/FeatureServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json')
          .then(res => res.json())
          .then(data => this.setState({ fires: data.features }))
      }
      displayFires = () => this.state.fires
        .filter(fire => fire.geometry !== null)
        .map(fire => fire.geometry.rings)
        .map(rings => <Polygon 
          paths = { rings.reduce((acc, ring) => acc.concat(convert_ring_coords(ring)), []) }
          fillColor     = "#BF5E4B"
          fillOpacity   = {0.45}
          strokeColor   = "#6B352A"
          strokeOpacity = {0.9}
          strokeWeight  = {1}
        />)
      render() {
        return (
          <div className="mapBox">
            <Map
              google        = {this.props.google}
              zoom          = {8}
              style         = {mapStyles}
              initialCenter = {{ lat: 37.7749, lng: -122.4149 }}
            >
              {this.displayFires()}
            </Map>
          </div>
        )
      }
    }
    

    Except for a more functional code style (which you can ignore), basically all I've changed was:

    1. new Polygon() and <Polygon> is not the same thing. You should return the latter. JSX translates to something like React.createElement(Polygon,...) not to new Polygon(...). OK, you've fixed that.

    2. As per docs and per source code, Polygon should be created as

      <Polygon
        paths         = {coords}
        fillColor     = "#BF5E4B"
        fillOpacity   = {0.45}
        strokeColor   = "#6B352A"
        strokeOpacity = {0.9}
        strokeWeight  = {1}
      />
      

      and not as

      <Polygon
        paths         = {coords}
        options       = {{...}}
      />
      

      your options are ignored

    3. this.displayFires() in componentDidMount does nothing, so it should be removed.

      As a side note: also at the time of this.displayFires() call this.state is not changed yet. But it shouldn't change the outcome because, as I said, this.displayFires() have no effect in componentDidMount... but this.state.polygons.push in your new version of code can have an effect... or I'd better say will introduce bugs. You should never do that.