Limit to multiple countries using GooglePlacesAutocomplete with react-native - react-native

I have seen a few posts explaining how to set multiple countries for google places autocomplete in javascript/react as so:
componentRestrictions: {country: ["gb", "fr"]}
but for react-native GooglePlacesAutocomplete, the advice is to put a components option within query. Unsure if here we can pass multiple countries... have tried and failed to pass an array here as looks like it needs to just be a string containing one country code. Would appreciate any help...
<GooglePlacesAutocomplete
placeholder={placeholder}
listViewDisplayed={true}
fetchDetails={true}
textInputProps={{
borderColor: color,
fontSize: 18,
borderWidth: 1,
borderRadius: 4,
flex: 1,
padding: 7
}}
onPress={(data, details = null) => {
console.log(data, details)
}}
query={{
key: googleApiKey,
language: "en",
components: "country:gb",
types: types ? types : null
}}
/>

You can use the component restrictions like so components: "country:gb|country:us"
See full code example below
<GooglePlacesAutocomplete
placeholder={placeholder}
listViewDisplayed={true}
fetchDetails={true}
textInputProps={{
borderColor: color,
fontSize: 18,
borderWidth: 1,
borderRadius: 4,
flex: 1,
padding: 7
}}
onPress={(data, details = null) => {
console.log(data, details)
}}
query={{
key: googleApiKey,
language: "en",
components: "country:gb|country:us",
types: types ? types : null
}}
/>

Related

react-native-google-places-autocomplete results are white

Unable to see the list items in the result list. Spent a full day figuring out what it might be, still unable to resolve it.
When search results appear, I cannot see the text. listview style doesn't color the text.
<GooglePlacesAutocomplete
returnKeyType={'default'}
fetchDetails={true}
minLength={2}
placeholder="Search"
textInputProps={{
placeholderTextColor: '#32a852',
returnKeyType: 'search',
}}
onPress={(data, details = null) => {
// 'details' is provided when fetchDetails = true
console.log(data, details);
}}
query={{
key: GOOGLE_API_KEY,
language: 'en',
}}
styles={{
textInput: {
height: 38,
color: '#5d5d5d',
fontSize: 16,
},
predefinedPlacesDescription: {
color: '#1faadb',
},
listView: {color: 'black', zIndex: 100000}, // doesnt work, text is still white?
}}
/>
</View>
In styles, add description for changing the color or any other style attribute.
styles = {{
...
description : {color : 'black'}
}}

Validate a phone number with React Native Phone Number Input?

How can i format then check if the phone number is valide to make the update with with React Native Phone Number Input ? i used the isValidNumberfuntion to check if the number is valid but i want to format it before with onChangeFormattedText method :
export default class PhoneUserInput extends PureComponent {
...
render() {
return (
<PhoneInput
onChange={(value) => {
isValidNumber(value) ? updateNumber('phoneNumber', value) : value
}
defaultValue={defaultValue}
placeholder="Enter Phone Number"
defaultCode="US"
keyboardType="phone-pad"
withDarkTheme
withShadow
autoFocus
textContainerStyle={{
backgroundColor: 'black',
}}
textInputStyle={{
color: '#fff',
fontFamily: 'calibri',
fontSize: Fonts.sizes.header,
borderBottomWidth: 1,
borderBottomColor: 'rgba(255,255,255,0.3)',
}}
codeTextStyle={{
color: '#fff',
}}
flagButtonStyle={{
backgroundColor: '#000',
color: '#fff',
}}
/>
);
}
}
you can access your onChangeFormattedText like this
onChangeFormattedText={(text) => {
isValidNumber(text) ? updateNumber('phoneNumber', text) : text
setFormattedText(text);
console.log(text
}}

React Native: Warning: Each child in a list should have a unique "key" prop

I'm quite new to React Native and have a question.
I get this warning: Each child in a list should have a unique "key" prop.
I've tried everything. Now I even have Math.random() as key and I still get the warning.
Home.js:
return(
<ScrollView style={styles.container}>
<StatusBar barStyle='light-content' />
<ImageBackground source={image} style={styles.image} imageStyle={styles.image2}>
<LinearGradient colors={['transparent', 'rgba(249,249,249,1)' ]} locations={[.4, 1]}
style={{
position: 'absolute',
left: 0,
right: 0,
top: 0,
height: 400
}} />
<TouchableOpacity activeOpacity={0.9} style={styles.topNews} onPress={()=> navigation.navigate('WebView')}>
<Text style={styles.topCategoryText}>ITALIAN LEAGUE</Text>
<Text style={styles.topTitleText}>Juventus legend: Ronaldo is natural to be criticized</Text>
<Text style={styles.topSourceText}>CNN Sport</Text>
</TouchableOpacity>
</ImageBackground>
<View style={{marginHorizontal: 10, flex: 1}}><RNMasonryScrollView
colums='2'
columnStyle={{flexDirection: 'column'}}
oddColumnStyle={{flex: 1, marginRight:15, marginLeft:10}}
evenColumnStyle={{flex:1,marginLeft:15}}
>
{[
<NewsDetail Key='1' title="Papers: Salah eager for Barca move" category='LA LIGA' imageSrc='https://en.as.com/en/imagenes/2020/06/11/football/1591881357_315795_noticia_normal.jpg'/>,
<NewsDetail Key='2' title="Man Utd struggles 'mentally impacting' Pogba, says France boss Deschamps" category='PREMIER LEAGUE' imageSrc='https://resources.premierleague.com/premierleague/photo/2019/06/20/88784d96-ef4b-4414-8b59-517c15b162a5/MW1-EditorialLead-new.png'/>,
<NewsDetail Key='3' title="Arsenal's complete player: The meteoric rise of Vivianne Miedema" category='PREMIER LEAGUE' imageSrc='https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTupBTx2is9w3Z7pIhrorpPDMTFHmQhS1Ypmg&usqp=CAU'/>,
<NewsDetail Key='4' title="Mourinho hit with suspension by UEFA" category='SERIE A' imageSrc='https://www.telegraph.co.uk/content/dam/football/2018/02/13/TELEMMGLPICT000153853426_trans_NvBQzQNjv4BqwD2sfO9joeQ6RY-qlTATNB2cSHopZMn-aCc647VHTAY.jpeg'/>,
<NewsDetail Key='5' title="'Ronaldo is definitely faster than me!' – Bolt" category='LA LIGA' imageSrc='https://resources.premierleague.com/premierleague/photo/2018/08/10/bf1acdf0-7b10-4dfe-8844-06f0f18d5c38/2018-08-10T192712Z_1257041591_RC18CE142CA0_RTRMADP_3_SOCCER-ENGLAND-MUN-LEI.JPG'/>,
<NewsDetail Key='6' title="Southgate admits to fears over Maguire's career" category='LIGUE 1' imageSrc='https://images.daznservices.com/di/library/GOAL/a8/c9/vivianne-miedema-goal-50-gfx_nuhcgkr4tthu1kyux2ymq4y4l.jpg?t=-1147520971&quality=60&w=1200'/>,
]}
</RNMasonryScrollView></View>
</ScrollView>
)
NewsDetail.js
import React, {useState, useEffect} from 'react';
import {View, Text, StyleSheet, Image, Dimensions } from 'react-native';
const NewsDetail = (props) => {
const random = Math.random()
const ViewWidth = 157.5
// const [imageSize, setImageSize] = useState({width: 0, height: 0});
// const [viewSize, setViewSize] = useState({width: 0, height: 0});
const [imageHeight, setHeight] = useState(0);
const myUri = props.imageSrc;
useEffect(() => {
Image.getSize(myUri, (width, height) => {
setHeight(height / (width / ViewWidth));
});
}, [])
if(imageHeight > 0){
console.log(random)
return (
<View style={styles.newsDetail} key={`${random}`}>
<Image
resizeMode='cover'
style={{
width: ViewWidth,
height: imageHeight,
borderTopLeftRadius: 7,
borderTopRightRadius: 7,
}}
source={{ uri: myUri,}}
/>
<Text style={styles.textOne}>{props.category}</Text>
<Text style={styles.textTwo}>{props.title}</Text>
</View>)
} else return null;
}
const styles = StyleSheet.create({
image:{
width: '100%',
borderTopLeftRadius: 7,
borderTopRightRadius: 7
},
newsDetail:{
backgroundColor: "white",
marginTop: 10,
borderRadius: 7,
opacity: 0.9,
shadowColor: "grey",
shadowRadius: 5,
shadowOffset: {width: 0, height: 0},
shadowOpacity: 0.3
},
textOne:{
fontSize: 10,
color: '#7A7F82',
fontWeight: 'bold',
paddingTop: 10,
paddingHorizontal: 10,
paddingBottom:3
},
textTwo:{
fontSize: 14,
color: '#2D3041',
fontWeight: 'bold',
paddingHorizontal: 10,
paddingBottom:10
}
});
export default NewsDetail;
I dont know what to do. Any help? Also, is there any websites where I can pay to get quick help on questions I have about React Native? Similar to StackOverflow just you pay to get quick answers on all questions?
A proper way to generate a list is to create an array of objects, then you use map to display. In your codes, it's almost correct. You should use key instead of Key.
const articles = [
{ id: 1, title: "Papers: Salah eager for Barca move", category: 'LA LIGA', imageSrc: 'https://en.as.com/en/imagenes/2020/06/11/football/1591881357_315795_noticia_normal.jpg' },
{id: '2', title: "Man Utd struggles 'mentally impacting' Pogba, says France boss Deschamps", category: 'PREMIER LEAGUE', imageSrc: 'https://resources.premierleague.com/premierleague/photo/2019/06/20/88784d96-ef4b-4414-8b59-517c15b162a5/MW1-EditorialLead-new.png'},
{ id:'3',title: "Arsenal's complete player: The meteoric rise of Vivianne Miedema", category: 'PREMIER LEAGUE', imageSrc: 'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTupBTx2is9w3Z7pIhrorpPDMTFHmQhS1Ypmg&usqp=CAU'}]
<RNMasonryScrollView
colums='2'
columnStyle={{flexDirection: 'column'}}
oddColumnStyle={{flex: 1, marginRight:15, marginLeft:10}}
evenColumnStyle={{flex:1,marginLeft:15}}
>
{ articles.map((article) => {
return <NewsDetail key={article.id} title={article.title} imageSrc={article.imageSrc} />
})}
</RNMasonryScrollView>

Why are my React Native View heights inconsistent?

I have the following code:
return (
<>
<View style={styles.dashboardListItemContainer}>
<View style={styles.listItemBorder} />
</View >
</>
)
const styles = StyleSheet.create({
dashboardListItemContainer: {
minHeight: 73,
backgroundColor: COL_DARK_BG,
display: "flex",
flexDirection: "column",
},
listItemBorder: {
minHeight: 0.5,
backgroundColor: 'white',
}
});
Which produces the following result:
My question is, why are the lines inconsistently bright / appear to be different heights?
Also when I change column to row here: flexDirection: "row", the line disappears completely. I can't tell if this is a bug or there are errors in my code?
TIA.
Update:
I cannot solve this problem on any device, and I've tried different methods for determining the height.
borderBottomWidth: StyleSheet.hairlineWidth, looks like this:
You can see in the above picture some lines do not even show up.
borderBottomWidth: StyleSheet.hairlineWidth * 2, looks like this:
And height: 0.5, looks like this on a white background:
The problem is consistent across devices, it is at the edge of an item in a <FlatList>.
Android Emulator has less resolution, try on a real device, sometimes i have the same error, and when I run on a real device it looks good.
We can use flex value.
import React, { Component } from "react";
import { View, FlatList } from "react-native";
import { StyleSheet } from "react-native";
class App extends Component {
render() {
return (
<FlatList
data={[1, 2, 3, 4, 5, 6, 7, 8, 9]}
extraData={[1, 2, 3, 4, 5, 6, 7, 8, 9]}
horizontal={false}
renderItem={({ item, index }) => {
return (
<View style={styles.dashboardListItemContainer}>
<View style={styles.listItemBorder} />
</View>
);
}}
key={({ item, index }) => index}
/>
);
}
}
export default App;
const styles = StyleSheet.create({
dashboardListItemContainer: {
backgroundColor: "red",
display: "flex",
flex: 1,
minHeight: 73,
flexDirection: "column"
},
listItemBorder: {
minHeight: 0.5,
backgroundColor: "yellow"
}
});

I am using react-native-google-places-autocomplete to search for places and not able to configure for zip code

I have integrated https://github.com/FaridSafi/react-native-google-places-autocomplete successfully and now need only to know how to get suggestions from zip-code . Example: When i write '35801' in search text-input, It should give me 'Huntsville, AL' in suggestions instead other all address, 'Huntsville, AL' should be prioritised
My autocomplete component
<GooglePlacesAutocomplete
placeholder='Search'
minLength={2}
autoFocus={false}
returnKeyType={'search'}
keyboardAppearance={'light'}
listViewDisplayed={false}
fetchDetails={true}
keyboardShouldPersistTaps="handled"
renderDescription={row => row.description}
onPress={(data, details = null) => {
console.log(data,details);
this.setState({location:data.structured_formatting.main_text, user_long:details.geometry.location.lng, user_lat: details.geometry.location.lat })
}}
enablePoweredByContainer={false}
getDefaultValue={() => ''}
textInputProps={{
ref: (input) => {this.fourthTextInput = input}
}}
query={{
// available options: https://developers.google.com/places/web-service/autocomplete
key: 'api-key',
language: 'en',
region: "US", //It removes the country name from the suggestion list
types: '', // default: 'geocode'
components: 'country:us'
}}
styles={{
container: {width:width/1.4}
textInputContainer: {
backgroundColor: 'transparent',
margin: 0,
width: width / 1.4,
padding:0,
borderTopWidth: 0,
borderBottomWidth:0
},
textInput: {
textAlign: 'center',
minWidth: width/1.4,
borderColor: "#cbb4c0",
borderBottomWidth: 1,
color: '#5d5d5d',
fontSize: 14,
},
description: {
color:'#ac879a',
fontWeight: '300'
},
predefinedPlacesDescription: {
color: '#1faadb'
}
}}
currentLocation={false}
nearbyPlacesAPI='GooglePlacesSearch' // Which API to use: GoogleReverseGeocoding or GooglePlacesSearch
GoogleReverseGeocodingQuery={{// available options for GoogleReverseGeocoding API : https://developers.google.com/maps/documentation/geocoding/intro
}}
GooglePlacesSearchQuery={{
// available options for GooglePlacesSearch API : https://developers.google.com/places/web-service/search
rankby: 'distance',
type: 'cafe'
}}
GooglePlacesDetailsQuery={{
// available options for GooglePlacesDetails API : https://developers.google.com/places/web-service/details
fields: 'formatted_address',
}}
filterReverseGeocodingByTypes={['locality', 'administrative_area_level_3']}
debounce={200}
/>
The zipcode or postal code is found inside "details" returned from the onPress event.
It'll actually be inside an array of objects (address_components) inside it.
The thing is that its position can vary.
The best way I found was to iterate this array looking for the type "postal_code".
Here is what has worked for me:
const [postalCode, setPostalCode] = useState("")
return (
<GooglePlacesAutocomplete
placeholder='Search'
onPress={(data, details) => {
for (let i = 0; i < details.address_components.length; i++) {
if (details.address_components[i].types[0] === "postal_code") {
setPostalCode(details.address_components[i].long_name)
}
}
}}
enablePoweredByContainer={false}
fetchDetails={true}
onFail={(error) => console.log("Error at finding location: ", error)}
query={{
key: googleKey,
language: "en",
}}
/>
)
Edited in 08/07/21
Another option is to split the string received on details.formatted_address.
This might be easier.
I hope it hepls!
You can use the '(region)' type in the query prop.
<GooglePlacesAutocomplete
placeholder="Search"
onPress={(data, details = null) => {
// 'details' is provided when fetchDetails = true
console.log(data, details);
}}
query={{
key: GOOGLE_PLACES_API_KEY,
language: "en", // language of the results
types: "(regions)",
}}
/>
If you are looking to only search within a specific country use:
query={{
key: GOOGLE_PLACES_API_KEY,
language: "en", // language of the results
types: "(regions)",
components: "country:us",
}}