反应本机获取多标记[未处理的承诺拒绝:TypeError:TypeError:未定义不是对象(评估'this.state.markers.map

Posted

技术标签:

【中文标题】反应本机获取多标记[未处理的承诺拒绝:TypeError:TypeError:未定义不是对象(评估\'this.state.markers.map【英文标题】:React native fetch multi markers [Unhandled promise rejection: TypeError: TypeError: undefined is not an object (evaluating 'this.state.markers.map反应本机获取多标记[未处理的承诺拒绝:TypeError:TypeError:未定义不是对象(评估'this.state.markers.map 【发布时间】:2018-04-09 21:10:38 【问题描述】:

我试图从 Google Places (nearbysearch) API 获取数据,并在此基于我所做的查询返回位置列表的 JSON 对象。我只是想处理这些对象并获取它们的纬度和经度值并将它们标记为要在 MapView 中呈现和返回的标记,这就是我到目前为止所做的。 (请原谅我凌乱的代码,因为这是我第一次尝试这样做并第一次尝试事情)。

export default class Whereto extends Component<> 

constructor(props) 
    super(props);

this.state = 
    latitude: null,
    longitude: null,
    location: null,
    error: null,
    markers:[
        latlng: latitude: null, longitude: null
    ]
;

然后我使用地理定位库来查找我的当前位置,并稍后将其用作对附近地方 API 的查询

componentDidMount() 
        navigator.geolocation.getCurrentPosition(
            (position) => 
                this.setState(
                    latitude: position.coords.latitude,
                    longitude: position.coords.longitude,
                    error: null,
                );

            var myApiKey = '';

            fetch('https://maps.googleapis.com/maps/api/geocode/json?address=' + position.coords.latitude + ',' + position.coords.longitude + '&key=' + myApiKey)
                .then((response) => response.json())
                .then((responseJson) => 
                    //console.log('ADDRESS GEOCODE is BACK!! => ' + JSON.stringify(responseJson));
                   .... .....
                ) this section is not the complete code but it is working which is simply used to return my current location

在我的 componentdidMount() 函数下是获取到 Google Places nearsearch(API)

var apiPlaceskey = '';
                //https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&type=restaurant&keyword=cruise&key=YOUR_API_KEY



fetch('https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=' + position.coords.latitude + ',' + position.coords.longitude + '&radius=500&type=bus_station&key=' + apiPlaceskey)
                .then((respplaces) => respplaces.json())
                .then((responseJson2) => 
                    //console.log(JSON.stringify(responseJson2));
                    //var locationName = responseJson.results[0].address_components.filter(x => x.types.filter(t => t === 'administrative_area_level_2').length > 0)[0].short_name;
                    for (var i = 0, length = responseJson2.length; i < length; i++)
                        var data = json[i],
                           latlng = (responseJson2.results[0].geometry.location.lat, responseJson2.results[0].geometry.location.lng);
                    
                this.setState(
                    markers: latlng
                )

API 调用似乎是成功的,因为我确实得到了回报,这是一个示例..


  "html_attributions": [],
  "results": [
    
      "geometry": 
        "location": 
          "lat": 52.90050499999999,
          "lng": -1.478267
        ,
        "viewport": 
          "northeast": 
            "lat": 52.90185398029149,
            "lng": -1.476918019708498
          ,
          "southwest": 
            "lat": 52.89915601970849,
            "lng": -1.479615980291502
          
        
      ,
      "icon": "https://maps.gstatic.com/mapfiles/place_api/icons/bus-71.png",
      "id": "4e992af207c8ff3503999574d25155ccf9b48f70",
      "name": "Randolph Road",
      "place_id": "ChIJM0syu93weUgRXSKhX6Flay8",
      "reference": "CmRRAAAAaE7cMbH9gq0w1U18RFtzX1GsEjTb7G2msTt4sL1hnvb5DrwTpFyznlVc9TvlfkOSkmJwU-dMa_RAvTO_8hCe_FeGIpQjwxMs7izIMg_oWYtGyzu9jQ0aIL9a_dRO40KvEhCrcpisZYRNNpDJH6p31oa6GhQpwF8PSkltIQvmsLMabEAnJWQ3OA",
      "scope": "GOOGLE",
      "types": [
        "bus_station",
        "transit_station",
        "point_of_interest",
        "establishment"
      ],
      "vicinity": "United Kingdom"
    ,
    
      "geometry": 
        "location": 
          "lat": 52.900963,
          "lng": -1.478217
        ,
        "view ........
and here comes my render section.

render()

        return(
            <View style=styles.container>
                <Mainlogo/>

                <MapView style=styles.map>

                    <MapView.Marker
                        coordinate=
                            latitude: this.state.latitude,
                            longitude: this.state.longitude,
                            latitudeDelta: 0.02,
                            longitudeDelta: 0.02
                        
                        image=require('../img/my-pin-512.png')
                        title='you are here'
                    />

                    this.state.markers.map(marker => (
                        <MapView.Marker
                            coordinate=marker.latlng
                        />

                    ))

                </MapView>
            </View>
        )
    

经过多次调整、修改和网络搜索后,我没有运气,并不断收到此错误:

[Unhandled promise rejection: TypeError: TypeError: undefined is not an object (evaluating 'this.state.markers.map')] 22:23:24 ▼Warning: Failed prop type: The prop coordinate.latitude is marked as required in MapMarker, but its value is null.

新的错误

【问题讨论】:

这是在做什么? latlng = (responseJson2.results[0].geometry.location.lat, responseJson2.results[0].geometry.location.lng); 我试图从结果 json 中获取纬度和经度值,并从那里获得经度和纬度值作为我的标记的值。我认为 for 循环没有返回任何内容。 var busstoplat = responseJson2.results[0].geometry.location.lat; var bustolong = responseJson2.results[0].geometry.location.lng;将它放在一个变量中,比如获取纬度和经度 如果你在 setState 之前 console.log latlng,你会得到什么? 我越来越不确定了。 好的...但是当您循环时,您只是将数据更新到数组中的当前项目,因此一旦完成,它将始终 = 最后一个项目。不确定您到底要做什么,但我认为如果您在将响应设置为状态之前尝试调整响应,则需要使用 map。 【参考方案1】:

我认为这就是您要尝试做的...创建一个新数组,使用 lat/long 并将其设置为标记。用这个替换你的循环和 setState:

const markers = responseJson2.results.map((result) => (
  latlng: 
    latitude: result.geometry.location.lat,
    longitude: result.geometry.location.lng,
  
);

this.setState( markers );

【讨论】:

嗨,是的。准确定位我正在尝试做的事情。我认为我需要一个 for 循环的原因是因为我认为我需要在 json 中进行迭代 现在我似乎收到了这个错误:更新由 AIRMapMarker 管理的视图的属性坐标时出错,如果上面是这样,我添加了屏幕截图 我认为这是因为您在其中有一个默认值为空值的项目。尝试将标记默认为您所在州的空数组。【参考方案2】:

乍一看,这似乎是一个异步问题。

您的render 方法没有检查未定义的值。 这是我正在谈论的部分:

this.state.markers.map(marker => (
  // ...
))

将在您的 fetch 请求得到结果之前调用 render 方法。但是到那时 this.state.markers 不会被填充。

您应该添加某种占位符视图,可以在 google api 返回结果之前显示。

类似这样的:

render() 
  if (myContrivedCondition) return <View styles=styles.placeholder/>;

  // your render code

响应到达后,由于您的this.setState,它将触发组件更新。

希望这会有所帮助。

【讨论】:

我的人为条件?你的意思是我应该处理错误?如果(未定义)? 不,我的意思是,它可能应该在响应返回之前显示类似于占位符的内容。您的渲染方法正在尝试访问尚未在渲染方法中设置的状态。

以上是关于反应本机获取多标记[未处理的承诺拒绝:TypeError:TypeError:未定义不是对象(评估'this.state.markers.map的主要内容,如果未能解决你的问题,请参考以下文章

从反应原生/[未处理的承诺拒绝:FirebaseError:预期类型'ba',但它是:自定义Oa对象]中获取项目列表

未处理的承诺拒绝:TypeError:网络请求在expo react native 中失败

可能未处理的承诺拒绝(id 0)反应原生

未处理的承诺拒绝,从 API 获取数据

Axios 承诺处理 - 在 react-native 中获取“可能的未处理承诺拒绝 - 类型错误:网络请求失败”

react-native 错误:[未处理的承诺拒绝:错误:获取 Expo 令牌时遇到错误:TypeError:网络请求失败。]