Liza Catherine Ombyaw
Liza Catherine Ombyaw

Reputation: 904

React Native - Google Autocomplete API

My problem is the Text result of descriptions is overlapping to each other. I do not know if this a bug, I just can't make it solve it. I tried anything about the styles but nothing works. I need help from other with different perspective. Thank you for taking time to read this.

Image of the overlapping texts:

enter image description here

I also get a warning about the unique key prop, just adding this issue because it might be related to my problem.

Image of the Warning key prop: enter image description here

Here are my codes:

async onChangeDestination(destination) {
this.setState({ destination });
const apiUrl = `https://maps.googleapis.com/maps/api/place/autocomplete/json?key=${apiKey}
  &input=${destination}&location=${this.state.focusedLocation.latitude}, 
  ${this.state.focusedLocation.longitude
}&radius=2000`;
try {
  const result = await fetch(apiUrl);
  const json = await result.json();
  console.log(json);
  this.setState({
    predictions: json.predictions
  });
} catch (err) {
  console.log(err)
}
}

render() {
//For Prediction
const predictions = this.state.predictions.map(prediction => (
  <View style={styles.descriptionContainer}>
    <Text key={prediction.id} style={styles.descriptionText}>{prediction.description}</Text>
  </View>
));
//For Marker
let marker = null;
if(this.state.locationChosen) {
  marker = <MapView.Marker coordinate={this.state.markerPosition}/>
}
return(
  <View style={styles.container}>
    {/* <StatusBar backgroundColor={'transparent'} translucent={true}/> */}
    <MapView
      style={styles.map}
      initialRegion={this.state.focusedLocation}
      onPress={this.pickLocationHandler}
      showsUserLocation={true}
      ref={ref => this.map = ref} //For animating map movement
    >
      {marker}
    </MapView>
    {/* <TouchableOpacity onPress={this.getLocationHandler} style={styles.iconContainer}>
      <Icon name="md-locate" size={30} color="blue"/>
    </TouchableOpacity> */}
    <TextInput 
      placeholder="Search for an event or place!"
      style={styles.destinationInput}
      onChangeText={destination => {
        this.setState({destination});
        this.onChangeDestinationDebounced(destination)
      }}
      value={this.state.destination}
    />
    {predictions}
  </View>
);
} 

const styles = StyleSheet.create({
container: {
  zIndex: -1,
  alignItems: 'center',
},
map: {
  height: '100%',
  width: '100%'
},
iconContainer: {
  position: 'absolute',
  top: 60,
  right: 15,
  zIndex: 1
},
destinationInput: {
  position: 'absolute',
  zIndex: 10,
  width: '97%',
  top: 15,
  backgroundColor: 'white',
  borderRadius: 8,
  padding: 8
},
descriptionText: {
  color: 'black',
  position: 'absolute',
  zIndex: 10,
  top: 60,
},
descriptionContainer: {
  zIndex: 2,
  position: 'absolute',
  top: 20,
  height: Dimensions.get('window').height,
  width: Dimensions.get('window').width,
  justifyContent: 'space-between'
}
})

Upvotes: 0

Views: 779

Answers (1)

Harrie Pieters
Harrie Pieters

Reputation: 128

So I haven't been able to run the code, however your descriptionText style has position: 'absolute'. The behaviour you are seeing is therefor expected, as each text is placed on the same 'absolute' position. Removing this should give you the result you want.

The key warning is thrown as your descriptionContainer View is the root element in the map function, so this should have the key. Hopefully this helps, updated source code below with a small disclaimer that I wasn't able to test it.

async onChangeDestination(destination) {
this.setState({ destination });
const apiUrl = `https://maps.googleapis.com/maps/api/place/autocomplete/json?key=${apiKey}
  &input=${destination}&location=${this.state.focusedLocation.latitude}, 
  ${this.state.focusedLocation.longitude
}&radius=2000`;
try {
  const result = await fetch(apiUrl);
  const json = await result.json();
  console.log(json);
  this.setState({
    predictions: json.predictions
  });
} catch (err) {
  console.log(err)
}
}

render() {
//For Prediction
const predictions = this.state.predictions.map(prediction => (
  <Text key={prediction.id} style={styles.descriptionText}>{prediction.description}</Text>
));
//For Marker
let marker = null;
if(this.state.locationChosen) {
  marker = <MapView.Marker coordinate={this.state.markerPosition}/>
}
return(
  <View style={styles.container}>
    {/* <StatusBar backgroundColor={'transparent'} translucent={true}/> */}
    <MapView
      style={styles.map}
      initialRegion={this.state.focusedLocation}
      onPress={this.pickLocationHandler}
      showsUserLocation={true}
      ref={ref => this.map = ref} //For animating map movement
    >
      {marker}
    </MapView>
    {/* <TouchableOpacity onPress={this.getLocationHandler} style={styles.iconContainer}>
      <Icon name="md-locate" size={30} color="blue"/>
    </TouchableOpacity> */}
    <TextInput 
      placeholder="Search for an event or place!"
      style={styles.destinationInput}
      onChangeText={destination => {
        this.setState({destination});
        this.onChangeDestinationDebounced(destination)
      }}
      value={this.state.destination}
    />
    {this.state.predictions && this.state.predictions.length > 0 && (
       <View style={styles.descriptionContainer}>{predictions}</View>
    )}
  </View>
);
} 

const styles = StyleSheet.create({
container: {
  zIndex: -1,
  alignItems: 'center',
},
map: {
  height: '100%',
  width: '100%'
},
iconContainer: {
  position: 'absolute',
  top: 60,
  right: 15,
  zIndex: 1
},
destinationInput: {
  position: 'absolute',
  zIndex: 10,
  width: '97%',
  top: 15,
  backgroundColor: 'white',
  borderRadius: 8,
  padding: 8
},
descriptionText: {
  color: 'black',
},
descriptionContainer: {
  zIndex: 2,
  position: 'absolute',
  top: 20,
  height: Dimensions.get('window').height,
  width: Dimensions.get('window').width,
}
})

Upvotes: 2

Related Questions