Я использую response-native-maps и отображаю несколько маркеров с помощью array.map (). У меня также есть карусель, которая отображает некоторые фотографии и информацию о каждом маркере.
Обычно, когда пользователь нажимает на элемент в карусели, карта приближается к этому маркеру и отображает выноску, вызывая следующую функцию.
markers[index].showCallout()
, который будет отображать вызов для этого маркера. Поэтому мне нужно заполнить массив ссылками, чтобы я мог передать индекс, который покажет сноску, когда пользователь перемещает карусель.
Для начала я создал массив, который будет содержать некоторое состояние.
const [markers, setMarkers] = useState([]);
Вот функция array.map, которая генерирует все маркеры на карте.
{searchResults.map((marker, index) => {
return (
<MapView.Marker
key={marker.key}
ref={(m) => {
setMarkers((markers) => [[...markers], m]);
}}
onPress={() => onMarkerPress(marker, index)}
coordinate={{
latitude: marker.geopoint.latitude,
longitude: marker.geopoint.longitude,
}}>
<Callout>
<Text>{marker.price}</Text>
</Callout>
</MapView.Marker>
);
})}
Я получаю ошибку «Ошибка: превышена максимальная глубина обновления. может случиться, когда компонент повторно вызывает setState внутри componentWillUpdate или componentDidUpdate. React ограничивает количество вложенных обновлений для предотвращения бесконечных циклов. "
, потому что я пытаюсь заполнить массив с помощью этой строки.
ref={(m) => {setMarkers((markers) => [[...markers], m])}}
Не уверен, есть ли другой способ сделать это.
Приведенный ниже прием работает нормально, если вы используете компоненты класса
ref={ref => this.state.markers[index] = ref}
, но я использую функциональные компоненты в своем приложении.
Вот весь код
const HomeScreen = ({navigation}) => {
{
/************ Array for Rendering Items in Carousel */
}
const searchResults = [
{
key: '1',
photographerURL:
'https://images.pexels.com/photos/598917/pexels-photo-598917.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
price: 100,
photographerName: 'Brittany',
geopoint: {latitude: 38.8929372, longitude: -77.0025119},
},
{
key: '2',
photographerURL:
'https://images.pexels.com/photos/1264210/pexels-photo-1264210.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
price: 200,
photographerName: 'Franklin',
geopoint: {latitude: 38.8963932, longitude: -77.0030197},
},
{
key: '3',
photographerURL:
'https://images.pexels.com/photos/243757/pexels-photo-243757.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
price: 50,
photographerName: 'Bryan',
geopoint: {latitude: 38.8925739, longitude: -76.9987113},
},
];
/**
* Function to animate map.
* When the user moves the carousel, the map will zoom in to
* the region where that photographer is
*/
const mapRef = useRef(null);
const [carouselRef, setCarouselRef] = useState([]);
const [markers, setMarkers] = useState([]);
console.log(markers);
/**
* Zooms in on the region whenever the carousel item is changed
*/
const onCarouselItemChange = (index) => {
let location = searchResults[index];
{
mapRef.current.animateToRegion({
latitude: location.geopoint.latitude,
longitude: location.geopoint.longitude,
//Zoom Level
latitudeDelta: 0.01,
longitudeDelta: 0.01,
});
}
//markers[index].showCallout();
};
/**
* When a user clicks on the marker, the carousel jumps
* to that particular item
*/
const onMarkerPress = (location, index) => {
mapRef.current.animateToRegion({
latitude: location.geopoint.latitude,
longitude: location.geopoint.longitude,
//Zoom Level
latitudeDelta: 0.01,
longitudeDelta: 0.01,
});
carouselRef.snapToItem(index);
};
return (
<View style={styles.container}>
{/**************** Google Maps *************** */}
<MapView
style={styles.map}
ref={mapRef}
provider={PROVIDER_GOOGLE}
showsUserLocation
followsUserLocation
initialRegion={{
latitude: 38.8929372,
longitude: -77.0025119,
//Zoom Level
latitudeDelta: 0.01,
longitudeDelta: 0.03,
}}>
{searchResults.map((marker, index) => {
return (
<MapView.Marker
key={marker.key}
//ref={(m) => [setMarkers((markers) => [...markers, m])]}
onPress={() => onMarkerPress(marker, index)}
coordinate={{
latitude: marker.geopoint.latitude,
longitude: marker.geopoint.longitude,
}}>
<Callout>
<Text>{marker.price}</Text>
</Callout>
</MapView.Marker>
);
})}
</MapView>
{/***************** Carousel ***********/}
<Carousel
ref={(c) => {
setCarouselRef(c);
}}
data={searchResults}
horizontal
containerCustomStyle={styles.carousel}
onSnapToItem={(index) => onCarouselItemChange(index)}
layout={'default'}
//layoutCardOffset={`50`}
sliderWidth={screenWidth}
itemWidth={screenWidth * 0.8}
itemHeight={400}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
renderItem={({item}) => (
<Item
photographerName={item.photographerName}
uri={item.photographerURL}
price={item.price}
/>
)}
keyExtractor={(item) => item.key}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFill,
},
map: {
...StyleSheet.absoluteFill,
},
carousel: {
position: 'absolute',
bottom: 0,
marginBottom: '5%',
},
});
export default HomeScreen;