我有以下行动创作者:
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
你能指出我错在哪里吗?
答案 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的反应
答案 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>
);