地理定位 - 在React / Redux应用程序中无法获得经度和纬度

时间:2017-07-31 15:46:06

标签: reactjs geolocation redux

我有以下行动创作者:

export const getLocation = () => {
    const geolocation = navigator.geolocation;

    const location = new Promise((resolve, reject) => {
        if (!geolocation) {
            reject(new Error('Not Supported'));
        }

    geolocation.getCurrentPosition((position) => {
        resolve(position);
    }, () => {
        reject (new Error('Permission denied'));
    });
  });

  return {
      type: GET_LOCATION,
      payload: location
  }
};

关注GET_LOCATION类型的reducer:

case GET_LOCATION: {
          return {
              ...state,
              location: {
                  latitude: action.location.coords.latitude,
                  longitude: action.location.coords.latitude,

              }
          }
      }

我尝试在我的组件中使用这些数据,如下所示:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getLocation } from '../actions';
import { bindActionCreators } from 'redux';

class UserLocation extends Component {
     constructor(props) {
         super(props);
     }

     componentWillMount() {
         this.props.getLocation();
     }

     render() {
         return (
            <div>
                <div><span>latitude:</span>{this.props.location.latitude} 
            </div>
            <div><span>longitude:</span>{this.props.location.longitude} </div>
        </div>
    );
  }
}

const mapDispatchToProps = dispatch => {
    return bindActionCreators( { getLocation }, dispatch )
}

export default connect(null, mapDispatchToProps)(UserLocation);

但每次加载此组件时,我都会得到TypeError: Cannot read property 'latitude' of undefined

你能指出我错在哪里吗?

4 个答案:

答案 0 :(得分:0)

地理位置数据将以异步方式解析,并且在第一次呈现组件时不可用。您需要正确处理尚未提供数据的情况,并且有几种方法可以做到这一点。有关如何处理不可用数据的说明,请参阅文章Watch Out for Undefined State

答案 1 :(得分:0)

您应该使用componentWillReceiveProps从调度的操作接收返回的数据。

componentWillReceiveProps = (nextProps) => {
    if (this.props.location.latitude !== nextProps.location.latitude) {
      // You will have location object here that is returned from recuder
    }
  }

检查这种替代方式来调用地理编码来获取lat和long以及与redux的反应

https://medium.com/@eesh.t/auto-detect-location-react-component-using-google-geocoding-and-reverse-geocoding-in-autocomplete-66a269c59315

答案 2 :(得分:0)

您在装入组件之前在componentWillMount()中执行了请求,但这并不意味着组件将等待请求结束。因此,您应该在渲染方法中进行一些验证,例如if(!this.props.location) return <div>Loading...</div>

答案 3 :(得分:0)

我想我也使用了与您相同的Codepen中的示例,其中作者使用了非常简化的React Promise中间件版本。 但是建议您使用redux-promise-middleware,以便您可以控制如何兑现承诺。

因此,您应该在创建Redux存储时导入中间件并将其包括在applyMiddleware中:

import promiseMiddleware from 'redux-promise-middleware'

composeStoreWithMiddleware = applyMiddleware(
  promiseMiddleware(),
)(createStore)

在动作创建者中派遣的承诺必须在化简器中使用FULFILED 承诺后缀(还有另一种方法)相同,但是您应该对此感到满意,我也不是英语为母语的人,所以请注意_FULFILLED中的错别字。

case `${GET_LOCATION}_FULFILLED`:
  return {
    ...state,
    location: {
      latitude: action.location.coords.latitude,
      longitude: action.location.coords.latitude,
    }
  }

我使用render()方法中的location对象,因此可以使用const mapStateToProps,以便可以从那里使用它。

const mapStateToProps = (state) => {
  return {location: state.location};
};

然后,在组件的render方法中,您可以从道具中分解位置对象:

 render() {
   const { location: { latitude, longitude } } = this.props;
   return (
     <div>
       <div><span>latitude:</span>{latitude}</div>
       <div><span>longitude:</span>{longitude}</div>
     </div>
   );