Search code examples
react-nativereact-native-maps

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>
  );
}
}

Solution

  • 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>
          );
        }