0

我正在使用 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);
4

1 回答 1

0

好的,所以我找到了答案。要使用 _addItem 函数 onPress 替换 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'

); }

于 2017-04-24T18:24:41.180 回答