I have a problem. When I display a map with @rnmapbox/maps and that I want to navigate in my screens, the app freeze then crashes. I'm pretty sure that this is a rnmapbox problem because when I remove the code between <MapboxGL.MapView> and <MapboxGL.MapView/>, navigation works fine.
I use @react-navigation/native and @react-navigation/native-stack
Note that this issus don't append on iOS, only on Android.
Record of the issue : https://vimeo.com/723749736
Here is my code :
App.js
import React from 'react';
import MapScreen from './src/screens/MapScreen';
import PlaceDetailsScreen from './src/screens/PlaceDetailsScreen';
import VideoPlayerScreen from './src/screens/VideoPlayerScreen';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {NavigationContainer} from '@react-navigation/native';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {GestureHandlerRootView} from 'react-native-gesture-handler';
function App() {
const Stack = createNativeStackNavigator();
return (
<SafeAreaProvider>
<GestureHandlerRootView style={{flex: 1}}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Map"
component={MapScreen}
options={{headerShown: false}}
/>
<Stack.Group>
<Stack.Screen name="Details" component={PlaceDetailsScreen} />
<Stack.Screen
name="VideoPlayer"
component={VideoPlayerScreen}
options={{headerShown: false}}
/>
</Stack.Group>
</Stack.Navigator>
</NavigationContainer>
</GestureHandlerRootView>
</SafeAreaProvider>
);
}
export default App;
MapScreen.js
import React, {useState, useRef, useMemo, useCallback, useEffect} from 'react';
import {View, Text, PermissionsAndroid, Platform} from 'react-native';
import MapboxGL from '@rnmapbox/maps';
import BottomSheet, {BottomSheetScrollView} from '@gorhom/bottom-sheet';
import Styles from '../../Styles';
import PlaceBtn from '../components/PlaceBtn/PlaceBtn';
import IconPin from './../assets/icons/icon-locationPin.svg';
MapboxGL.setAccessToken(
'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
);
function MapScreen({navigation}) {
const [hasGeolocPermission, setHasGeolocPermission] = useState(false);
const [currentRegion, setCurrentRegion] = useState([4.824, 45.76]); //longitude, latitude
const [userLocation, setUserLocation] = useState();
const [nearestPoints, setNearestPoints] = useState([]);
const markers = require('../data/markers.json');
const route = require('../data/route.json');
const routeLine = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: route.points,
},
},
],
};
const bottomSheetRef = useRef(null);
const snapPoints = useMemo(() => ['13%', '75%', '100%'], []);
const handleSheetChanges = useCallback(index => {
console.log('handleSheetChanges', index);
}, []);
const requestLocationPermission = async () => {
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('location uses is granted');
setHasGeolocPermission(true);
} else {
console.log(granted);
console.log('location access denied');
}
} catch (error) {
console.warn('error while request location : ', error);
}
}
};
useEffect(() => {
requestLocationPermission();
}, []);
return (
<View style={Styles.container}>
<MapboxGL.MapView style={Styles.map} scaleBarEnabled={false}>
<MapboxGL.UserLocation
animated
showsUserHeadingIndicator
minDisplacement={1}
onUpdate={position => {
console.log('position : ', position);
}}
/>
<MapboxGL.Camera centerCoordinate={currentRegion} zoomLevel={14} />
{markers.map((marker, index) => {
if (marker.category === 'introduction') {
console.log('intro');
} else {
return (
<MapboxGL.PointAnnotation
key={index}
id={marker.id + ''}
coordinate={[marker.longitude, marker.latitude]}>
<IconPin width={35} height={35} fill={'#00c0aa'} />
</MapboxGL.PointAnnotation>
);
}
})}
<MapboxGL.ShapeSource id="line1" shape={routeLine}>
<MapboxGL.LineLayer
id="linelayer1"
style={{lineColor: 'red', lineWidth: 5}}
/>
</MapboxGL.ShapeSource>
</MapboxGL.MapView>
<BottomSheet
ref={bottomSheetRef}
handleIndicatorStyle={Styles.handleIndicator}
index={0}
snapPoints={snapPoints}
onChange={handleSheetChanges}>
<View style={Styles.bottomSheetContent}>
<Text style={Styles.bottomSheetTitle}>{route.name}</Text>
<BottomSheetScrollView>
{markers.map((place, index) => {
return (
<PlaceBtn
place={place}
navigation={navigation}
//isNear={nearestPoints.includes(place.id)}
/>
);
})}
</BottomSheetScrollView>
</View>
</BottomSheet>
</View>
);
}
export default MapScreen;
PlaceDetailsScreen.js
import React from 'react';
import {View, Text, TouchableOpacity} from 'react-native';
function PlaceDetailsScreen({navigation}) {
return (
<>
<TouchableOpacity
style={{backgroundColor: '#00FF00'}}
onPress={() => navigation.navigate('Map')}>
<Text>Go to MAP</Text>
</TouchableOpacity>
<TouchableOpacity
style={{backgroundColor: '#00FF00'}}
onPress={() => navigation.navigate('VideoPlayer')}>
<Text>Go to Video Player</Text>
</TouchableOpacity>
</>
);
}
```