我正在使用React本机地图,并在地图上显示业务标记。 我想调用api以根据新坐标获得新的领导能力。 我想做的是在事件“ onRegionChangeComplete”上调用api,它可以正常工作并在地图上显示新标记,但是我有一些问题:
代码
import React, { Component } from 'react'
import { View, Text, FlatList } from 'react-native'
import { inject, observer } from 'mobx-react/native'
import style from './style'
import I18n from '../../i18n'
import Icon from 'react-native-vector-icons/Feather'
import MapView, { PROVIDER_GOOGLE, Marker } from 'react-native-maps' // remove PROVIDER_GOOGLE import if not using Google Maps
import { BusinessDetailItem } from '../../components'
import { calcSize } from '../../utils'
import Colors from '../../utils/Colors'
import _ from 'lodash'
import MapView, { PROVIDER_GOOGLE, Marker } from 'react-native-maps'
@inject('UserStore')
@observer
class BusinessMap extends Component {
constructor(props) {
super(props)
this.state = {
details: {},
region: {
latitude: props.UserStore.Latitude,
longitude: props.UserStore.Longitude,
latitudeDelta: Math.abs(props.UserStore.Latitude / 5000),
longitudeDelta: Math.abs(props.UserStore.Longitude / 5000),
},
}
this.debounce = _.debounce(data => this.onRegionChangeComplete(data), 1000)
}
componentDidMount() {}
renderUserMarker = () => {
const { UserStore } = this.props
return <MapView.Marker tracksViewChanges={false} coordinate={{ latitude: UserStore.Latitude, longitude: UserStore.Longitude }} title={I18n.t('my_location')} />
}
renderBusinessMarkers = () => {
const { UserStore } = this.props
if (UserStore.orgs.length > 0) {
return UserStore.orgs.map((info, i) => (
<MapView.Marker
tracksViewChanges={false}
key={i}
coordinate={{ latitude: info.location.coordinates[1], longitude: info.location.coordinates[0] }}
title={info.org_name}
onCalloutPress={() => {
this.props.navigation.navigate('BusinessDetail', { org_id: info._id })
}}
/>
))
}
return null
}
onRegionChangeComplete = region => {
this.setState({ region })
let query = {
lat: region.latitude,
lng: region.longitude,
limit: 10,
}
await this.props.UserStore.getOrgsByLocation(query)
console.log('onRegionChangeComplete', region)
}
renderMap = () => {
console.log('this.state.region', this.state.region)
const { UserStore } = this.props
return (
<View style={style.view_address_map}>
<View style={style.view_map}>
<MapView
// scrollEnabled={false}
showsUserLocation
followUserLocation
toolbarEnabled={false}
showsIndoors={false}
moveOnMarkerPress={false}
style={style.map}
region={this.state.region}
onUserLocationChange={e => {
'onUserLocation', console.log(e.nativeEvent)
}}
onPress={() => {
console.log('onPres')
}}
onCalloutPress={e => {
'onCalloutPress', console.log(e.nativeEvent)
}}
onRegionChange={this.onRegionChange}
onRegionChangeComplete={this.onRegionChangeComplete}
>
{this.renderUserMarker()}
{this.renderBusinessMarkers()}
</MapView>
</View>
</View>
)
}
renderBusinessDetailItem = (appointment, index) => {
return <BusinessDetailItem {...appointment.item} navigation={this.props.navigation} addToFavouriteList={() => {}} />
}
renderBusinessList = () => {
return (
<View style={style.view_flat_last_minute_appointments}>
<FlatList
horizontal={true}
disableVirtualization={true}
contentContainerStyle={style.view_content_container_flat_list_last_minutes}
data={this.props.UserStore.orgs}
keyExtractor={(item, index) => `key-${index}`}
renderItem={this.renderBusinessDetailItem}
// ListEmptyComponent={this.renderEmptyComponent}
showsHorizontalScrollIndicator={false}
style={style.content_flat_list}
/>
</View>
)
}
render() {
const { container, view_close_icon, icon_close } = style
const { coordinates } = this.state.details
const { UserStore } = this.props
return (
<View style={container}>
<View style={view_close_icon}>
<Icon
name='x'
size={calcSize(60)}
color={Colors.black}
style={icon_close}
onPress={() => {
this.props.navigation.goBack()
}}
/>
</View>
{UserStore.orgs && this.renderMap()}
{this.renderBusinessList()}
</View>
)
}
}
export default BusinessMap
答案 0 :(得分:1)
鉴于API如此频繁地/每次加载标记时都会被调用,因此我对您的地图运行缓慢并不感到惊讶。
[减少api调用]可行的解决方案是创建一种标记的“区域缓存”,这样就无需再次查询以前加载的标记。
来自Four tips to Optimize Your Map with React Native :
减少通话量的有效方法是 创建本地缓存。例如,在每个请求之前,创建一个密钥 与您的参数(poi的类型,说明等)一起使用 请求并将其存储在查询区域旁边的状态中。它可以 这样完成:
示例代码:
const key = createKey({pinTypes, searchText});
this.setState({
queriedRegion: {
[key]: boundaries(region)
},
businessMarkers,
})
通过缓存已经查询的点,然后在获取新点之前,您可以检查上次调用是否使用相同的键以及包含当前键的区域进行。如果是这样,您就知道您已经拥有要显示的所有点,并且可以放心地忽略此请求(考虑到您始终查询区域中与标准匹配的所有点,并且不会根据缩放级别进行过滤)
if(
this.state.queriedRegion &&
this.state.queriedRegion[key] &&
isRegionWithin(boundaries(region), this.state.queriedRegion[key])
) {
//Do not query the points, they are already fetched !
return;
}
防止不必要的地图渲染的另一种方法是在自定义标记类中实现shouldComponentUpdate。然后,您可以使用控件指定仅当标记的ID被选中/未选中/已被缩放/缩放等时才希望渲染标记。
shouldComponentUpdate(prevProps) {
return prevProps.isSelected !== this.props.isSelected ||
prevProps.isZoomed !== this.props.isZoomed}
如果您有很多不需要显示的标记,则可以考虑使用“ clustering”,它会将不需要显示的标记束“分组”为一个大标记[如相对于许多小型应用程序而言],但从您的应用程序描述来看,我认为这并不特别适合您。
最后,我想回顾一下您的代码,以确保您的标记不会执行不必要的计算:如果您可以将prop作为参数传递,这将减少处理时间并提高性能!
希望这会有所帮助
[逐个,我发现this piece of code,它加载了许多标记,我认为您可能会感兴趣。但是请考虑以上几点!]