🍣

【ReactNative】react-native-maps応用編②「マーカーのonPressイベントとマップのonPressイベント」

2020/12/22に公開

はじめに

react-native-mapsの応用編第二弾になります。

バックナンバーは以下の通りです。

https://zenn.dev/nekoniki/articles/0c40e9267b81e4

https://zenn.dev/nekoniki/articles/1be7f07be211d8

今回ですが、react-native-mapsでマーカーを使った場合に遭遇するケースです。

サンプル

例えば以下のようにMapMarkerにそれぞれonPressイベントが設定されているとします。

Test.tsx
import React from 'react';
import { Alert } from 'react-native'
import MapView, { Region, Marker, LatLng } from 'react-native-maps';

const Test: React.FC = () => {
    // 初期表示位置
    const initialRegion : Region = {
        latitude : 35.689521,
        longitude : 139.691704,
        latitudeDelta : 0.0460,
        longitudeDelta : 0.0260,
    }

    // マーカーの表示位置
    const coordinate : LatLng = {
        latitude : 35.689421,
        longitude :139.691604
    }
    
    return(){
      <MapView initialRegion={initialRegion} onPress={()=> { Alert.alert("マップを押したよ") }} >
          <Marker coordinate={coordinate} onPress={()=>{ Alert.alert("マーカーを押したよ") }} />
      </MapView>
    }
}

マップを押した場合とマーカーを押した場合でそれぞれ違う処理を行いたいのですが、この書き方だとマーカーを押した場合に 「マップ押下時のイベントも一緒に実行」 されてしまいます。

HTML + JSの世界でいうところのイベントバブリングが起きている状態です。

対処法はstopPropagation()を使う

これはreact-native-mapsというよりreact-nativeの各コンポーネントの仕様のようなもので、当然バブリングを止める手段も用意されています。
onPressの場合だと引数として押下時のイベントが引数として受け取れる(MapEvent型)ので、stopPropagation()を実行します。

<Marker coordinate={coordinate} onPress={(e : MapEvent) => {
            // マップにonPressイベントが伝播するのを止める 
            e.stopPropagation();
            Alert.alert("マーカーを押したよ")
        }} />

こうすることでマーカーを押した場合に上位要素であるマップのonPressが呼ばれることを防げます。

まとめ

今回はreact-native-mapsでよく使うマップ・マーカーのonPressイベントのバブリングとその対処法について紹介しました。

よく見かけるのが 「マップをタップした位置にマーカーを置く」 のと 「マーカーをタップした際に何かしらの処理をする」 ようなアプリです。
その場合、今回の例のようにどちらにもonPressイベントを設定しないといけないため、バブリングに注意する必要があります。

基本といえばそれまでですが、意外と忘れがちなので気を付けましょう。

Discussion