Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error on using fitToElements #180

Closed
gathole opened this issue Apr 14, 2016 · 31 comments
Closed

Error on using fitToElements #180

gathole opened this issue Apr 14, 2016 · 31 comments

Comments

@gathole
Copy link

gathole commented Apr 14, 2016

To set the Google Map zoom level to show all the markers, I was suggested to use fitToElements but I am getting error "not included points"

Here is my code and markers have 2 points:

  componentDidMount() {
    this.refs.map.fitToElements(true);
  }

  render() {
    var markers = this.props.markers || [];
    return (
      <MapView
        ref="map"
        style={[styles.map, this.props.mapStyle]}
        initialRegion={this.getInitialRegion(markers)}>
        {markers.map(marker => (
          <MapView.Marker 
            coordinate={marker.latlng}
            title={marker.title}
            description={marker.description}
            image={marker.image}/>
        ))}
      </MapView>
    );
  }
@christopherdro
Copy link
Collaborator

Whats the data in marker.latlng look like?

@gathole
Copy link
Author

gathole commented Apr 14, 2016

let markers = [{
      latlng: {
        latitude: this.props.currentBooking.pickup_latitude,
        longitude: this.props.currentBooking.pickup_longitude
      },
      image: require('../images/customer.png')
    }, {
      latlng: {
        latitude: this.props.driverLocation.latitude,
        longitude: this.props.driverLocation.longitude
      },
      image: require('../images/onway.png')
    }];

Latitude and Longitude are string value... I think it supposed to be a Point... Let me know if I am correct and Thanks for reply

@jrichardlai
Copy link
Contributor

Not sure if thats the issue but can you cast the latitude and longitude to a float?

@gathole
Copy link
Author

gathole commented Apr 15, 2016

I cast the latitude and longitude to a float but getting the same error "No included points". Can you please explain where should I mention points and what would be the values (x and y) to be passed in Point?

Let me clarify one more thing is that I am working on Android.

@DennisMG
Copy link
Contributor

The docs says fitToElements method receives argument animated: Boolean ... I'm not sure what a Animated: Boolean is!

@DennisMG
Copy link
Contributor

I found the solution, you just have to add an empty js object, like this: this.refs.map.fitToElements(true,{}); I don't know why but it worked.

@simonhintersonnleitner
Copy link

@DennisMG this.refs.map.fitToElements(true,{}); do not work for me.

@DennisMG
Copy link
Contributor

DennisMG commented Apr 20, 2016

@simonhintersonnleitner I thought it solved the problem but sometimes throws the error described above and other times works perfectly

@DennisMG
Copy link
Contributor

try changing the fitToElements function in react-native-maps/android/src/main/java/com/AirMaps/AirMapView.java for this:

public void fitToElements(boolean animated) {
        int counter = 0;
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (AirMapFeature feature : features) {
            if (feature instanceof AirMapMarker) {
                Marker marker = (Marker)feature.getFeature();
                builder.include(marker.getPosition());
                counter++;
            }
            // TODO(lmr): may want to include shapes / etc.
        }
        if(counter > 0){
            LatLngBounds bounds = builder.build();
            CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 150);
            if (animated) {
                startMonitoringRegion();
                map.animateCamera(cu);
            } else {
                map.moveCamera(cu);
            }
        }
    }

It worked for me.

@gathole
Copy link
Author

gathole commented May 11, 2016

@DennisMG : Yeah, above change prevent it from a crash but found fitToElements is not working. I am calling this method in componentDidMount but doesn't look map is adjusting zoom level.

@ryanmclaughlin
Copy link

👍 Anyone able to fix this?

@ryanmclaughlin
Copy link

I feel like this is a required feature for any map with markers or am I the only one?

@igrayson
Copy link
Contributor

I've come into this as well.

Adding some logging to render, componentDidMount, and AirMapManager.java#addView seems to indicate that React Native (android) may not wait for ViewGroupManager#addView to finish adding child views, before "finishing" render and invoking componentDidMount.

In fact, when configuring my component to quickly render several times (intentionally updating state during render to trigger a tight loop), we can cycle through many renders before the first render's children are added to the java ViewGroupManager instance.

This indicates we can't depend on component lifecycle methods like componentDidMount to perform side-band actions (like directly invoking native methods via this.refs.map.fitToElements), and that fitToElements, and perhaps the other direct methods are dangerous to use within the react component lifecycle.

If I haven't made a bad assumption, it looks like the cleanest fix would be to replace fitToElements as a method, and instead implement that functionality using a prop passed to the AirMapView through the same, possibly-delayed path that children are added.

I.e.,

  render() {
    var markers = this.props.markers || [];
    return (
      <MapView
        style={[styles.map, this.props.mapStyle]}
        fitToElements={MapView.ANIMATED_FIT} // or MapView.IMMEDIATE_FIT
        initialRegion={this.getInitialRegion(markers)}>
        {markers.map(marker => (
          <MapView.Marker 
            coordinate={marker.latlng}
            title={marker.title}
            description={marker.description}
            image={marker.image}/>
        ))}
      </MapView>
    );
  }

@bcalik
Copy link

bcalik commented Jun 26, 2016

@igrayson We actually just need a onMapReady event.

@igrayson
Copy link
Contributor

igrayson commented Jun 26, 2016

I don't believe that would help. The map is rendered (and becomes 'ready') before any children/markers are added. Markers are later added one at a time (via ViewGroupManager#addView).

We need to know when the map is rendered, and all children have been added -- i.e., what you normally expect componentDidMount to provide.

@igrayson
Copy link
Contributor

igrayson commented Jul 1, 2016

We haven't found a consistent workaround for this yet.

Has anyone found a reliable way to fitToElements without crashing the app with not included points?

@fabianbormann
Copy link

fabianbormann commented Jul 5, 2016

In my desperation I used the setTimeout function..

setTimeout(() => {
  this._map.fitToElements(false);
}, 1000);

which worked for me, but it feels so hacky and I hope I can remove it asap.

@ddresch
Copy link

ddresch commented Jul 23, 2016

Hmm I'm new to RN at all and at the moment I'm also using this hacky setTimeout approach.

What about a onReady prop of MapView which takes following object?

<MapView onReady={{markerCount: myMarkers.length, callback: myCallbackFunc}}

It's not a beauty :) but at least the component knows the amount of markers which need to be present and if the internal count is true calls the callback. Just my 2cent as I said I'm totally new to this!

@erickreutz
Copy link

Any fix for this?

@symmetriccurve
Copy link

symmetriccurve commented Aug 17, 2016

<MapView
      **ref = {(MapRef)=> MapRef.fitToElements(true)}**
      loadingBackgroundColor= '#ffffff'
      showsPointsOfInterest = {false}
      showsIndoors = {false}
      showsTraffic ={false}
      showsBuildings = {false} //A Boolean indicating whether the map displays extruded building information.
      loadingEnabled = {true} //If true a loading indicator will show while the map is loading.
      style={{flex:1}}
      //showsCompass = {true}
      //showsScale = {true}
      >

calling a ref after a component is mounted and applying the fitToElements to the callback variable fixed the issue for me.

this is something like onMapReady event but on react component
more here: https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute

@ddresch
Copy link

ddresch commented Aug 20, 2016

@symmetriccurve thx for this hint. I checked it and it's not working on my side, getting error "Cannot read property 'fitToElements" of null" That's why it's only working with this hacky setTimeout.

@mynamespace
Copy link

Not working for me either

@symmetriccurve
Copy link

@ddresch
Probably the ref has not been set yet which is the case 'fitToElements" of null"

Try this out :
ref = { (MapRef)=> if( MapRef !=null ) { MapRef.fitToElements(true) } }

@BaptisteT
Copy link

@symmetriccurve this is not working

@mynamespace
Copy link

Alternative way: find the region that contains all the markers and change the map's region prop accordingly.

@BaptisteT
Copy link

Yes, this is what I ended up doing!

@symmetriccurve
Copy link

@BaptisteT . Does it throw a error ?

@ryankask
Copy link
Contributor

ryankask commented Oct 2, 2016

A patch was added that will included in 0.9.0 basically doing what @DennisMG mentioned so at least the application won't crash like it does now. fitToElements() unfortunately still doesn't work probably for the reason @igrayson mentioned.

I ended up just writing fitToElements in JS and doing what @mynamespace said.

@lucasbento
Copy link
Contributor

fitToElements wasn't working here either so I used the onLayout prop callback on MapView:

onMapLayout = () =>
    this.map.fitToElements(true);

render() {
  return (
    <MapView
      ref={ref => this.map = ref}
      onLayout={this.onMapLayout}
    >
      {/* stuff */}
    </MapView>
  );
}

@rborn
Copy link
Collaborator

rborn commented Oct 18, 2018

closing, very old

@christopherdro
Copy link
Collaborator

I’m closing this issue because it has been inactive for a while. This probably means that it is not reproducible or it has been fixed in a newer version. If it’s an enhancement and hasn’t been taken on for so long, then it seems no one has the time to implement this.

Please reopen if you still encounter this issue with the latest stable version.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests