我正在使用React Native为IOS移动设备创建地图应用。我正在使用React Natives MapView组件,我正在尝试使用onPress函数中的onRegionChange事件更新区域,这样当用户输入地址时,onRegionChange中的setState将使用放置在由地址输入的地址上的标记来呈现该地址。用户。
我试过在我的_addItem函数onPress事件中调用on RegionChange函数。我传入了该函数this.state.region,其中我使用this.state.coordinate设置等于标记的坐标,但我在控制台中不断收到此错误:
错误:您试图在对象上设置值为latitude
的键33.77709834885268
,该对象应该是不可变的并且已被冻结。
我还尝试创建一个名为onMarkerChange的新函数,并在标记的坐标上调用setState,然后调用_addItem函数onPress中的onMarkerChange函数,我得到用户输入的新地址上呈现的标记,但它需要我超出区域并且用户必须多次单击标记以缩放到区域。
有人可以通过查看我的代码告诉我我做错了什么。非常感谢!
这是我的代码:
class Map_app2 extends Component {
constructor(props){
super(props);
this.state = {
region: {
latitude: 33.753746,
longitude: -84.386330,
latitudeDelta: 0.0922,
longitudeDelta: 0.0121
},
coordinate: {
latitude: 33.749249,
longitude: -84.387314,
latitudeDelta: 0.0922,
longitudeDelta: 0.0121
},
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2})
};
this.itemsRef = this.getRef().child('items');
this.onRegionChange = this.onRegionChange.bind(this);
this.onMarkerChange = this.onMarkerChange.bind(this);
}
onRegionChange(region){
this.setState({region});
}
onMarkerChange(coordinate){
this.setState({coordinate})
}
getRef(){
return firebaseApp.database().ref();
}
listenForItems(itemsRef){
itemsRef.on('value', (snap) => {
var items = [];
snap.forEach((child) =>{
items.push({
address: child.val()._address,
_key: child.key
});
console.log(items)
});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(items),
});
});
}
componentDidMount() {
this.listenForItems(this.itemsRef);
}
render() {
console.log(this.state.region);
console.log(this.state.coordinate)
return (
<View style={styles.container}>
<MapView
style={styles.map}
region={this.state.region}
onRegionChange={this.onRegionChange}
>
<MapView.Marker
coordinate={{
latitude: this.state.coordinate.latitude,
longitude: this.state.coordinate.longitude
}}
onPress= {() => console.log(this.state.coordinate)}>
</MapView.Marker>
<ActionButton
onPress={this._addItem.bind(this)}
title="Search Address"/>
</MapView>
<ListView
dataSource= {this.state.dataSource}
renderRow= {this._renderItem.bind(this)}
style= {styles.listview}
enableEmptySections={true}>
</ListView>
</View>
);
}
_addItem() {
AlertIOS.prompt(
'Look up address',
null,
[{text: 'Cancel', onPress: () => console.log('Cancel Pressed'),
style:'cancel'},
{
text: 'Enter',
onPress: (value) => Geocoder.geocodeAddress(value).then(res => {
// res is an Array of geocoding object (see below)
this.state.coordinate.latitude = res[0].position.lat
this.state.coordinate.longitude = res[0].position.lng
this.state.region = this.state.coordinate
this.onRegionChange(this.state.region)
this.itemsRef.push({address: res[0].formattedAddress})
})
.catch(err => console.log(err))
}],
'plain-text'
);
}
_renderItem(item) {
const onPress = () => {
AlertIOS.prompt(
'Edit or Delete Item',
null,
[
// {text: 'Edit', onPress: (text) =>
this.itemsRef.child(item._key).update({address: this.state.region})},
{text: 'Delete', onPress: (text) =>
this.itemsRef.child(item._key).remove()},
{text: 'Cancel', onPress: (text) => console.log('Cancelled')}
]
);
};
return (
<ListItem item={item} onPress={onPress} />
);
}
}
AppRegistry.registerComponent('Map_app2', () => Map_app2);
答案 0 :(得分:0)
好的,我找到了答案。要使用onad的_addItem函数替换this.state.region区域中的日期,我需要将this.state.region设置为等于我用来将地址转换为坐标的地理编码器的纬度和经度。所以我需要使用以下内容:
_addItem() {
AlertIOS.prompt(
'Look up address',
null,
[{text: 'Cancel', onPress: () => console.log('Cancel Pressed'),
style:'cancel'},
{
text: 'Enter',
onPress: (value) => Geocoder.geocodeAddress(value).then(res => {
// res is an Array of geocoding object (see below)
this.state.coordinate.latitude = res[0].position.lat
this.state.coordinate.longitude = res[0].position.lng
//I needed to set this region equal to the conversion of the address from within the geo coder to the latitude and longitude of the address.
this.state.region = {latitude: res[0].position.lat,
longitute: res[0].position.lng}
this.onRegionChange(this.state.region)
this.itemsRef.push({address: res[0].formattedAddress})
})
.catch(err => console.log(err))
}],
'plain-text'
); }