简体   繁体   中英

Access ref prop from MapView component for use by outside function

Is there a way to access the ref property from MapView component from an outside function?

Basically, I have:

  1. A main component which has a render method that will call (<MyMap />)

  2. <MyMap /> is an exported function with the MapView Component. Inside the MapView component, I make a reference (ref=map=>(mapRef=map) and want to pass that reference to the function that generates my markers (<PinData /> .

  3. In <PinData /> , I want to use the onPress event for the marker to zoom in and move to the marker using the MapView.animateToRegion method.

I keep getting the undefined is not an object (evaluating 'mapRef.animateToRegion').

Do I have to create component classes (instead of using exported functions) for the map reference to work in order to render the MapView and Markers components?

Ex: Main Class component:

render(){
     return(
          <View>
             <MyMap region={this.state.region} 
                    pinData={this.state.pinsData} 
                    myPins={this.state.myPins}
                    mapRef={this._mapRef} />
          </View>
)}

MyMap function renders my MapView component.

export const MyMap= ({ region, pinsData, myPins}) => {

  return (
    <View style={styles.container}>
      <MapView
        provider={PROVIDER_GOOGLE}
        ref={map => (mapRef = map)}
        style={styles.userMap}
        region={region}
      >
        <PinData pinsData={pinsData} myPins={myPins} />
      </MapView>
    </View>
  );

PinData Function which is used to generate markers on my map.

export const PinData = ({ pinsData, myPins, mapRef }) => {
  return pinsData.map((pin, index) => (
    <Marker
      key={index}
      ref={ref => (markers[index] = ref)}
      coordinate={{
        longitude: pin.coordinates.lng,
        latitude: pin.coordinates.lat
      }}
      onPress={focusMarker(mapRef, pin, index)}
    />
  ));
};

onPress function which would zoom into one of the pins using the animateToRegion method associated with the MapView object.

focusMarker = (mapRef, location, index) => {
  mapRef.animateToRegion({
    latitude: location.coordinates.lat,
    longitude: location.coordinates.lng,
    latitudeDelta: 0.005,
    longitudeDelta: 0.005
  });
};

You can pass an onPress prop to PinData

export const MyMap= ({ region, pinsData, myPins}) => {
    const mapRef = useRef();

  focusMarker = (location) => {
    mapRef.current.animateToRegion({
      latitude: location.coordinates.lat,
      longitude: location.coordinates.lng,
      latitudeDelta: 0.005,
      longitudeDelta: 0.005
    });
  };

  return (
    <View style={styles.container}>
      <MapView
        provider={PROVIDER_GOOGLE}
        ref={mapRef}
        style={styles.userMap}
        region={region}
      >
        <PinData pinsData={pinsData} myPins={myPins} onPress={focusMarker}/>
      </MapView>
   </View>
);

}

export const PinData = ({ pinsData, myPins, onPress }) => {
  return pinsData.map((pin, index) => (
    <Marker
      key={index}
      ref={ref => (markers[index] = ref)}
      coordinate={{
        longitude: pin.coordinates.lng,
        latitude: pin.coordinates.lat
      }}
      onPress={() => onPress(pin)}
    />
  ));
};

I figured it out, thanks to Tuan's answer. The code above works. What I wasnt understanding before is how the onPress worked. Basically, from my understanding, the logic is as follows:

Within the MyMap function, we define the focusMarker function.

Then create a prop within the called onPress and set it equal to the focusMarker function.

In the PinData function, we now take this prop(onPress) in as a parameter and set the onPress prop in the Marker component to an anonymous function which will execute the focusMarker function with a parameter of pin. In this function, onPress which is passed in as a parameter for the exported function is actually the focusMarker function itself and we are calling it with a parameter of pin. Hope that makes sense to anyone who can utilize this. Thanks again Tuan. Appreciate it. I was stumped on this for a while.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM