React本机映射在onRegionChange时调用API请求



我正在使用React本机地图,并且在地图上显示业务标记。我想打电话给API以获得新的稳定性。我尝试做的是将API称为事件为" onRegionChangecomplete",它可以在地图上显示并显示新标记,但我有一些问题:

  1. 地图非常缓慢,需要时间来加载地图(新街道并加载地图)
  2. 即使我使用debounce来调用onRegionChangeComplete,它每次都称为API,而且看起来不好。
  3. 当我使用地图移动时,我需要第一个位置

代码

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

我并不惊讶您的地图很慢,因为API被称为如此频繁/每次加载标记时。

一个可行的解决方案[减少API调用]将是创建标记的一种"区域缓存",以便以前加载的标记不需要再次查询。

从四个提示中,用反应本机优化地图:

减少您需要拨打的电话量的一种有效方法是 创建本地缓存。例如,在每个请求之前,创建一个密钥 带有您的参数(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;
}

防止不必要的地图渲染器的另一种方法是在您的自定义标记类中实现Insimponentuptate。然后,您有控制权以指定仅当选择/未选择/未选择/Zoomed等时,才希望您的标记才能渲染。

shouldComponentUpdate(prevProps) {
    return prevProps.isSelected !== this.props.isSelected ||
           prevProps.isZoomed !== this.props.isZoomed}

如果您有许多可能不需要显示的标记,则可能会考虑"聚类",哪些"群体"捆在一起,将一堆不必要的标记堆在一起成一个大标记[与许多小型小标记相反],但是从您的应用程序的描述来看,我认为这不适用于您。

最后,我要说的是查看您的代码,以确保您的标记不会执行不必要的计算:如果您可以通过道具作为参数,这将减少处理时间并提高性能!

希望这会有所帮助

[通过,我发现这件代码加载了许多标记,我认为可能会让您感兴趣。但请考虑以上几点!]

相关内容

  • 没有找到相关文章

最新更新