MouseWarrior
MouseWarrior

Reputation: 51

How can I pass a reference of a mapview to another component?

I have a map view, and in another componenet, I would like to be able to have a function that animates that mapview. That function would need a reference to my map view. How can I access my maps reference inside another component?

I have a snack expo that reproduces my problem exactly here as well as some code below. Please note which files are classes and which are functions. The files are too big in my projects, I do not want to change them

EDIT: Could I use some sort of state library such as Context to store the ref?

export default function App() {
  return (
    <View style={styles.container}>
      <Map/>
      <AnimateMapButton/>
    </View>
  );
}

I cant access this._map for obvious reasons. How can I access this?

export default class AnimateMapButton extends React.Component {

  goToLocation = () => {
    this._map.animateToRegion({
      latitude: 103.1561,
      longitude: -47.1651,
      latitudeDelta: 0.0025,
      longitudeDelta: 0.0025,
    })
  }

  render() {
  return (
      <View style={{height: 75, width: 200, backgroundColor: 'red', position: 'absolute', top: 100}}>
        <TouchableOpacity onPress={() => this.goToLocation()}>
        <Text style={{fontSize: 20, }}>Click to animate the map</Text>
        </TouchableOpacity>
      </View>
  );
}
}
export default class Map extends React.Component {
  render(){
  return (
    <View style={styles.container}>
      <MapView 
        style={styles.map}
        ref={map => this._map = map}
       />
    </View>
  );
}
}

Upvotes: 1

Views: 637

Answers (2)

Gavara.Suneel
Gavara.Suneel

Reputation: 616

I suggest you use React.forwardRef in such scenarios.

map.js

export default React.forwardRef((props, ref) => {
   return (
    <View style={styles.container}>
      <MapView
        ref={ref}
        style={styles.map}
      />
    </View>
  );
})

animatemapbutton.js

export default class AnimateMapButton extends React.Component {

  render() {
  return (
      <View style={{height: 75, width: 200, backgroundColor: 'red', position: 'absolute', top: 100}}>
        <TouchableOpacity onPress={() => this.props.onGotoLocation()}>
        <Text style={{fontSize: 20, }}>Click to animate the map</Text>
        </TouchableOpacity>
      </View>
  );
}
}

  

App.js

 export default function App() {
       const _mapRef = React.createRef();
    
        goToLocation = () => {
        _mapRef.current.animateToRegion({
          latitude: 103.1561,
          longitude: -47.1651,
          latitudeDelta: 0.0025,
          longitudeDelta: 0.0025,
        })
      }
    
      return (
        <View style={styles.container}>
          <Map ref={_mapRef}/>
          <AnimateMapButton onGotoLocation={goToLocation} />
        </View>
      );
    }

Upvotes: 1

vinayr
vinayr

Reputation: 11244

You have to use a combination of reference and event callback method in the root component like this -

App.js

export default function App() {
  const mapRef = React.useRef();

  const goToLocation = () => {
    mapRef.current.animateToRegion({
      latitude: 37.78825,
      longitude: -122.4324,
      latitudeDelta: 0.0922,
      longitudeDelta: 0.0421,
    })
  }

  return (
    <View style={styles.container}>
      <Map mapRef={mapRef} />
      <AnimateMapButton goToLocation={goToLocation} />
    </View>
  );
}

animatemapbutton.js

export default function Animatemapbutton({ goToLocation }) {
  return (
      <TouchableOpacity
        style={{ height: 75, width: 200, backgroundColor: 'red', position: 'absolute', top: 100 }}
        onPress={() => goToLocation()}
      >
        <Text style={{fontSize: 20, }}>Click to animate the map</Text>
      </TouchableOpacity>
  );
}

map.js

export default function Map({ mapRef }) {
  return (
    <View style={styles.container}>
      <MapView
        ref={mapRef}
        style={styles.map}
      />
    </View>
  );
}

Upvotes: 0

Related Questions