React:如何使用用户当前位置的更新状态而不是初始状态

Posted

技术标签:

【中文标题】React:如何使用用户当前位置的更新状态而不是初始状态【英文标题】:React: How to use user current-location's update state not initial state 【发布时间】:2020-12-08 07:44:39 【问题描述】:

我正在为我的应用程序使用React-native-maps。我制作了假的 json 餐厅数据并获取了该数据,并使用Marker 显示在我的地图上。在 React-native-maps 中有一个道具名称 initialRegion 我在其中放置了硬编码的初始状态。我使用expo-location & expo-permission 来显示用户的当前位置。

我想显示用户当前位置和餐馆之间的距离,为此我使用了一个名为geolib 的包。所有的逻辑工作正常。但问题是当我渲染应用程序时,它会显示用户的硬编码初始状态,5 秒后状态得到更新,然后我可以看到准确的当前位置。我想等待用户当前位置的更新状态。但我不知道该怎么做。

我还在Expo-Snack 中分享我的代码。 Ps: it only works on android and ios' on snack 这是我的代码

    import React, useState, useEffect,useCallback from 'react';
import  Dimensions, StatusBar, StyleSheet, Text,
  TextInput, TouchableOpacity, View, Button, FlatList  from 'react-native';
import Mapview, Marker, Callout, PROVIDER_GOOGLE from 'react-native-maps' 
import * as Location from 'expo-location';
import * as Permissions from 'expo-permissions';
import datas from './components/datas.json'
import  getDistance, getPreciseDistance  from 'geolib';

export default function App() 
  const [state, setstate] = useState(
    "latitude": 60.1098678,
    "longitude": 24.7385084,
    "latitudeDelta": 1,
    "longitudeDelta": 1
  );

  useEffect(() => 
    _onMapReady();
  , [_onMapReady]);

  const _onMapReady = useCallback(async () => 
    const  status  = await Permissions.askAsync(Permissions.LOCATION);
    if (status !== `granted`) 
    
    const location = await Location.getCurrentPositionAsync( "accuracy": Location.Accuracy.High );
    setstate(
      ...state,
      "latitude": location.coords.latitude,
      "longitude": location.coords.longitude
    );
  , [state]);
    const  latitude, longitude  = state;
       const propertiesInRegion = datas.data.map((location) => 
        const dis = getPreciseDistance( 
           "latitude": location.location.lat, "longitude": location.location.lng ,
           latitude, longitude 

        );
        return 
          ...location,
          "distance": dis / 1000 
        ;
      );

  return (
    <View style=styles.container>
    <Mapview
        provider=PROVIDER_GOOGLE
        initialRegion=state
        showsIndoors=true
        showsMyLocationButton=true
        zoomControlEnabled=true
        zoomEnabled=true
        zoomTapEnabled=true
        showsScale=true
        showsBuildings=true
        showsUserLocation=true
        showsCompass=true
        onMapReady=_onMapReady
    
        style=styles.mapStyle>
        
          datas.data?.map((i) => 
            return (
              <Marker
                coordinate=
                  "latitude": i.location.lat,
                  "longitude": i.location.lng
                
                animation=true
                key=i.id
               
              >
                <Callout
                  style= "width": 100, "height": 50 >
                  <View>
                    <Text>i.Property</Text>
                  </View>
                </Callout>
              </Marker>
            );
          )
        
        
      </Mapview>

      
      <FlatList
       style=styles.flatList
       data=propertiesInRegion
       renderItem=(item)=>
         return <React.Fragment>
         <Text style=styles.text>item?.Property</Text>
         <Text>item.distance</Text>
         </React.Fragment>
       
      />
     
    </View>
  );

const styles = StyleSheet.create(
  container: 
    "flex": 1,
    "alignItems": `center`,
    "justifyContent": `center`

  ,
 text:
    color: "white", 
    fontSize:15,
    marginBottom:10
  ,
 
  mapStyle: 
    "height": Dimensions.get(`window`).height,
    "width": Dimensions.get(`window`).width
  ,
  flatList: 
    "position": `absolute`,
    "bottom": 32,
    "width": 300,
    "height": 200,
    "borderRadius": 24,
    "justifyContent": `center`,
    "alignItems": `center`, 
    backgroundColor:"#5F4B8BFF",
    
  , 
 
);

【问题讨论】:

您可以在获取当前位置时显示活动指示器,然后使用animateToRegion更新地图 我在 expo-snacks 中分享我的代码。你能用代码给我看吗,我是 React-native-maps 的新手。谢谢 @krisna 不管你是否是地图新手,这是一个通用技巧。您可以最初声明状态变量 isLoading: true,当它为 true 时,您可以显示活动指示器,当您的新数据到来时,将其设置为 false。 【参考方案1】:

@HussainSherwani

我将 mapRef 设为 null 并在地图视图中传递了 ref=mapRef 然后这样调用它:

  const mapRef = React.useRef(null);
  useEffect(() => 
    animateToRegion();
  ,
  [state, animateToRegion]);
  const animateToRegion = useCallback(() => 
    mapRef?.current?.animateToRegion(state, 1000);
  , [state]);
我使用可选链接来消除未定义的错误。但问题还是显示了初始状态。如何在状态更新时显示ActivityIndicator

【讨论】:

ref=mapref=mapRef?有错别字吗? 没有伙伴。我被这个animatedToRegion的用例困住了

以上是关于React:如何使用用户当前位置的更新状态而不是初始状态的主要内容,如果未能解决你的问题,请参考以下文章

React Native Undefined 不是对象 - 地理位置

React Native Geolocation Watchposition不会实时更新

我可以在 React js 中使用 useRef 挂钩而不是 onChange 事件来更新状态吗?

如何在 React 状态下更新对象

使用 fusedlocationapi 获取位置,而无需在一段时间后请求位置更新

React 组件表在更新状态后被多次渲染或复制