Some images not showing up, linking not working in react native - react-native

EDIT: The image issue has been resolved, but still not sure about Linking.
Okay so I'm having two weird questions. And apologies ahead of time for the code.
First thing's first, some images will simply not display even though they're valid. When running this in my IOS simulator, the very first image will not display. But some images always work.
The second thing, and let me know if this should be two separate questions, is linking to an external site. It doesn't appear to be able to do the Linking.open in IOS. So I wondered what is the easiest way, through linking or otherwise, of simply opening an external URL in both android and IOS?
Thanks a lot!
openUrl(url) {
Linking.canOpenURL(url).then(supported => {
if (supported) {
Linking.open(url);
} else {
console.log('nope :: ' + url);
}
}).catch(err => console.error('An error occurred', err));
// browser.open(url);
},
renderImage(event, index) {
if (this.state.showBox && this.state.boxIndex == index) {
return (
<View>
<TouchableHighlight onPress={()=>this._clickImage(event, index)}>
<Image source={{ uri: event.image }} style={[styles.image, this.calculatedSize(), this.getImageStyles(event.featured), { height: 100 }]} />
</TouchableHighlight>
<View style={{ flexDirection:'row', padding: 15 }}>
<Text style={styles.price}>{event.price}</Text>
<Text style={styles.time}>{event.time}</Text>
<TouchableHighlight onPress={()=>this.openUrl(event.website)}>
<Text style={styles.btn}>Website</Text>
</TouchableHighlight>
</View>
{renderif(event.venue)(
<TouchableHighlight onPress={()=>this.openUrl(event.venue)}>
<Text style={styles.btn}>Venue</Text>
</TouchableHighlight>
)}
</View>
)
} else {
return (
<View>
<TouchableHighlight onPress={()=>this._clickImage(event, index)}>
<Image source={{ uri: event.image }} style={[styles.image, this.calculatedSize(), this.getImageStyles(event.featured)]} />
</TouchableHighlight>
</View>
)
}
},

That's because some of your images are trying to load image from http connection.IOS apps require you to use https for images.
For example in this
{
title: 'test',
image: 'http://www.piedmontpark.org/images/bird_pine_warbler_330.jpg',
featured: true,
category: 'Music',
price: '$8.00',
time: '7:00 PM-11:00 PM',
venue: '',
website: 'http://google.com'
}
Your 'image' is trying to load a jpg from http.
Check this out on how to configure your info.plist to accept http

Related

How to render local images according to the id of the items fetched from url?

I have created an images folder in assets and I have saved some pictures in it. And I wanted to render those pictures according to the id of the items that I have fetched from the url, I renamed all those picture according the id of the items fetched. But it is not working. Does anybody can help me to figure out or if you have another suggestion to do it I am open for suggestions. Here you can see what I am trying to do:
export default function App() {
const [material, setMateral] = useState([]);
useEffect(() => {
axios
.get("http://localhost:5000/materals/")
.then((products) => {
setMaterial(materials.data.response);
})
.catch((err) => {
console.error(err);
});
}, []);
return (
<View style={styles.container}>
{material.map((material) => {
console.log(material);
const { id, name, categories, genders, brands, price } = material;
<View style={styles.materialsContainer}>
<View style={styles.materialsItem}>
<Image
source={"../../assets/images/${id}.jpg"}
alt={id}
style={styles.thumbnail}
/>
<Text style={styles.box} numberOfLines={1}>
${id}
</Text>
<Text style={styles.box}${name}</Text>
<Text style={styles.box}${categories}</Text>
<Text style={styles.box}${genders}</Text>
<Text style={styles.box}${brands}</Text>
<Text style={styles.box}$ ${price}</Text>
</View>
</View>;
})}
);
}
Here is what I got in the console
Your problem is here:
<Image
source={"../../assets/images/${id}.jpg"}
alt={id}
style={styles.thumbnail}
/>
You should be using backticks (``) rather than double quotation to perform string interpolation.
<Image
source={`../../assets/images/${id}.jpg`}
alt={id}
style={styles.thumbnail}
/>
I'm also not sure what you're trying to do in your Text components
<Text style={styles.box}${name}</Text>
Are you trying to add a '$' as a string before the name? If you're trying to perform string interpolation, the ${} format only works when using backticks. But in this case, you could just do this.
<Text style={styles.box}>{name}</Text>

React Native: Open link on image click

I have an array arr of dictionary whose elements go like:
{url: 'https://stackoverflow.com/', picUrl: 'link to pic', ...}
I want to open the i-th link when the i-th image is clicked. My code goes as:
arr = this.example[key];
var arrayLength = arr.length;
for(var i = 0; i < arrayLength; i++) {
console.log(arr[i]);
console.log(arr[i].url);
var x = arr[i].url;
views.push(
<View>
<ImageBackground
source={{uri: arr[i].picUrl}}
style={{ width: '100%',aspectRatio: 1, height: undefined }}>
<TouchableOpacity
onPress={() => Linking.openURL(x)}
// or onPress={() => Linking.openURL(arr[i].url)}
style={{flex: 1}}>
</TouchableOpacity>
</ImageBackground>
.....
When I click the image, I get this error:
undefined is not an object (evaluating 'arr[i].url')
I then verified that arr[i] etc. aren't undefined by:
console.log(arr[i])
console.log(arr[i].url)
and got correct values ('https://stackoverflow.com/' for this example).
When I hardcode the value to 'https://stackoverflow.com/', everything seems to work fine, which means there is an issue with the line Linking.openURL(arr[i].url) only. What exactly? I don't know :(
I've been stuck at this issue for quite some time, saw a few posts related to this, but nothing help. Can someone help me resolve this issue? Thanks...
Update:
I changed onPress={() => Linking.openURL(arr[i].url)} to:
onPress={() => Alert.alert(arr[i])}
and I got a completely blank alert!
Then, I did:
var x = arr[i].url
and changed the earlier line to:
onPress={() => Linking.openURL(x)}
Now, for all of the images, the link is set to arr[length-1].url, that is, its equal to the value of the url of the very last image in the array!
You can first check if app can handle this URL using canOpenURL
<TouchableOpacity
onPress={() => Linking.canOpenURL(arr[i].url)
.then((supported) => {
if (!supported) {
console.log("Can't handle url: " + arr[i].url);
} else {
return Linking.openURL(arr[i].url);
}
})
.catch((err) => console.error('An error occurred', err));
}
style={{flex: 1}}>
<ImageBackground
source={{uri: arr[i].picUrl}}
style={{ width: '100%',aspectRatio: 1, height: undefined }}>
</ImageBackground>
</TouchableOpacity>
Update
Instead of for loop you can use map,
let views = arr.map(data => <View>
<ImageBackground
source={{uri: data.picUrl}}
style={{ width: '100%',aspectRatio: 1, height: undefined }}>
<TouchableOpacity
onPress={() => Linking.openURL(data.url)}
style={{flex: 1}}>
</TouchableOpacity>
</ImageBackground>
</View>
)

Card counting functionality react native

I am trying to make an e-commerce app and everything working only the cart icon counts not updating when the user adds an item to cart.
Here is my main page where i am calling component:
<Header headerTitle={this.state.wineD.name} lefticonType={'back'} navigation={this.props.navigation} />
Here is component code:
componentDidMount(){
//API code here and updating response count in state.
if(response.data.success){
this.setState({
cartItems: (response.data.data.cart.items != '' && (response.data.data.cart.items).length > 0)?
(response.data.data.cart.items).length : 0
})
this.props.changeLoaderStatus();
}
}
<FlatHeader
leftIcon={<Icon name={leftIcon} size={20} color="#FFF" />}
leftIconHandler={() => {
(this.props.lefticonType == 'bars' ?
this.props.navigation.dispatch(DrawerActions.openDrawer())
: goBack())
}}
centerContent={
<View style={{width: width*0.7,alignItems:'center'}}>
<Text numberOfLines={1} style={{ color: '#FFF',fontSize:22,fontWeight:'bold' }}>{this.props.headerTitle}</Text>
</View>
}
rightIcon={<Group><Icon name="shopping-cart" size={20} color="#FFF" />
<View style={{width:16,height:16,borderRadius:8,backgroundColor:'red',justifyContent:'center',
alignItems:'center',marginBottom:14}}>
<Text style={{fontSize:10,color:'#fff',fontWeight:'bold'}}>{this.state.cartItems}</Text></View></Group>}
rightIconHandler={() => this.props.navigation.navigate('Cart')}
large
style={{ backgroundColor: '#d7b655' }}
/>
This is the screen where from other component updating the cart
Anyone have solution please share here.
If I understood correctly your problem, you may need to modify this.setState in this way:
componentDidMount(){
//API code here and updating response count in state.
if(response.data.success){
this.setState({
cartItems: (response.data.data.cart.items != '' && (response.data.data.cart.items).length > 0)?
(response.data.data.cart.items).length : 0
},()=>{
this.props.changeLoaderStatus(); }) } }
try this and let me know if it works for you.

I want my app to not show articles or give them low priority to those that have already been seen

I have a basic article app like inshorts i am storing all the articles in database which i fetch on the opening and display them in card format.Now I want to implement that when a card id viewed it should get low priority and render at the end next time the app is opened on that mobile.
I have no clue how to implement this.
This is how i am currently rendering it
renderArtciles=()=>{
let len=this.state.dataSource.length;
return this.state.dataSource.map((item,i)=>{
this.state.id=item._id;
this.state.priority=item.priority;
this.state.views=item.views;
if (i == this.state.currentIndex-1)
{
return(
<Animated.View key={item._id} {...this.state.panResponder.panHandlers} style={this.state.swiped_pan.getLayout()}>
< View style={{ flex: 1,position:'absolute',height:height,width:width,backgroundColor:'white'}}>
< View style={styles.Imagebody}>
<Image source={{ uri:item.img.data }} style={styles.image} />
</View>
<View style={styles.inner}>
<Text>{item.body} i==={i}{this.state.currentIndex} </Text>
</View>
</View>
</Animated.View>
)
}
else if (i < this.state.currentIndex)
{
return null
}
if (i == this.state.currentIndex)
{
return(
<Animated.View key={item._id} {...this.state.panResponder.panHandlers} style={this.state.pan.getLayout()}>
< View style={{ flex: 1,position:'absolute',height:height,width:width,backgroundColor:'white'}}>
< View style={styles.Imagebody}>
<Image source={{ uri:item.img.data }} style={styles.image} />
</View>
<View style={styles.inner}>
<Text>{item.body} i==={i}{this.state.currentIndex} </Text>
</View>
</View>
</Animated.View>
)
}
else{
return(
<Animated.View key={item._id} >
< View style={{ flex: 1,position:'absolute',height:height,width:width,backgroundColor:'white'}}>
< View style={styles.Imagebody}>
<Image source={{ uri:item.img.data }} style={styles.image} />
</View>
<View style={styles.inner}>
<Text>{item.body} i==={i}{this.state.currentIndex} </Text>
</View>
</View>
</Animated.View>
)
}
}
).reverse()
}
You could make use of AsyncStorage to store which items have been viewed (and how many times) in a JSON object which you can increment every time an item is viewed, and then retrieve again when the app is opened (and store in some state variable). You can then work out your ordering/priority logic based on the number of views.
To store the items you would do something like this:
_storeData = async () => {
try {
var itemsJson = {items: [
{item_id: 'foo', view_count: 10},
{item_id: 'bar', view_count: 5}
]}
await AsyncStorage.setItem('ItemViews', JSON.stringify(itemsJson));
} catch (error) {
// Error saving data
}
};
And to retrieve the items on app open you would do something like this:
_retrieveData = async () => {
try {
const items = await AsyncStorage.getItem('ItemViews');
// Rest of your code
} catch (error) {
// Error retrieving data
}
};

how to use pagination on product listing React Native

I am creating react native app. on app category page i am fetching data and from live url in json form and post it into product page.
fetching data code:-
handlePressProduct(id) {
var url='http://www.furnitureinfashion.net/menu_category_listing.php?cat_id=';
fetch(url+id, {
method: 'GET'
}).then((response) => { return response.json() } )
.then((responseJson) => {
console.log(responseJson);
Actions.product({data:responseJson})
})
}
on product page i am getting data like this:-
{this.props.data.map((dataImage,Index1)=>
<View key={Index1}>
{dataImage['ProductId'] != undefined && (
<View style={productStyle.homeimg1}>
<TouchableOpacity onPress={this.handlePressProduct.bind(this,dataImage['ProductId'])}>
<Image source={{uri: uri+dataImage['Image']}} style={{width: 130, height: 130}} />
<Text style={productStyle.title}> {dataImage['ProductName']}</Text>
<Text style={productStyle.shopbutton}>View Details</Text>
</TouchableOpacity>
{dataImage['Options'] != '' &&(
<Text style={productStyle.cartbutton} >Select Option</Text>
)}
{dataImage['Options'] == '' &&(
<Text style={productStyle.cartbutton} >Add to cart</Text>
)}
<Text> RRP{dataImage['RRPPrice']}</Text>
<Text> Our Price{dataImage['OurPrice']}</Text>
<Text style={productStyle.buymorebutton} >Buy & Save More Today</Text>
<Text style={productStyle.shiptext} >Free Shipping</Text>
</View>
)}
</View>
)}
in array product data is too large so, i want to add pagination on product page. but i don't know how to do?