Dynamically set uri of a react native <Image /> - android

I am trying to build a FlatList which will have an icon on the left (pretty much like any Contacts app) and I'm trying to dynamically load an image based on the name of the element
<Image
style={styles.image}
source={{uri: `./assets/${this.props.name}.png`}}
/>
Which is not allowed by React Native, as stated by their Image docs.
Are there any workaround?

if your image is in your project (eg assets folder) you can not create dynamically, the most you can do is an array to select, like this:
var icons = [ require('image!my-icon-active') ,require('image!my-icon-inactive')];
<Image
style={styles.image}
source={icons[1]}
/>
but you can save the images in a folder and read from your local storage using 'file://' or 'data://' like you are reading from Web, that can be dinamically link:
let uri = 'file://'+this.state.pathToResources+'/'+href;
<Image
style={{width: 400, height: 400}}
resizeMode='contain'
source={{uri}}
/>
You can use the lib
https://github.com/itinance/react-native-fs
for you ready from local disk of your smartphone, but you need manage the height e width.
For more read https://facebook.github.io/react-native/docs/images.html#uri-data-images

Just create a variable in the state:
constructor(props) {
super(props);
this.state = {
imgUri: ""
}
}
...
<Image
style={styles.image}
source={{uri: this.state.uri}}/>
Update the uri by calling this.setState({imgUri: "foobar"})

Related

React Native - How to load local image using the uri in Image Component?

I know we can load the local image with:
<Image source={require('folder/image.png')}/>
But i need to load the image like this:
<Image source={{uri: 'folder/image.png'}}/>
It works for network images but it doesn't work for local images and even it does not give any error for local images and silently does not display the image. Can anyone tell how to load the local image using the uri property?
In case you are using Expo to build your React Native application, this might help:
1) Install expo-asset: expo install expo-asset
2) Initialize and set your imageUri:
import {Asset} from 'expo-asset';
const imageURI = Asset.fromModule(require('../../assets/test.png')).uri;
3) In my case, I needed it on a Thumbnail from NativeBase:
<Thumbnail square source={{uri: imageURI}}/>
Docs: https://docs.expo.io/versions/latest/sdk/asset/
These are the three ways to render images in react-native ,
In your case you can encode the image
you can require image
source={require('/react-native/img/favicon.png')}
you can get image from web
source={{uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
or you can encode the image
source={{uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg=='}}
as doc suggested as below
export default class DisplayAnImage extends Component {
render() {
return (
<View>
<Image
source={require('/react-native/img/favicon.png')}
/>
<Image
style={{width: 50, height: 50}}
source={{uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
/>
<Image
style={{width: 66, height: 58}}
source={{uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg=='}}
/>
</View>
);
}
}
or you can create a json file that contains the encoded string of the image
image.json
{imageString: '64encodedString'}
them import the file
import image from 'image.json';
then image
<Image source:{{uri:image.imageString}} />
Add android:requestLegacyExternalStorage="true" in AndroidManifest file.
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="false"
android:requestLegacyExternalStorage="true" <=== here
android:theme="#style/AppTheme">

React-Native Disable Image Cache on Android

i am trying to use a random image generator for a demo app i am creating.
i have tried the endpoints:
http://thecatapi.com/api/images/get?format=src&type=gif&size=small
http://junglebiscuit.com/images/random/rand_image.pl
but when i add a list of images to my page with:
<View>
<Image
source={{ uri: 'http://thecatapi.com/api/images/get?format=src&type=gif&size=small' }}
style={{ width: 100, height: 100 }}
/>
<Image
source={{ uri: 'http://thecatapi.com/api/images/get?format=src&type=gif&size=small' }}
style={{ width: 100, height: 100 }}
/>
<Image
source={{ uri: 'http://thecatapi.com/api/images/get?format=src&type=gif&size=small' }}
style={{ width: 100, height: 100 }}
/>
</View>
the expectation is that for each Image component, a different image would be displayed. strangly, this does not work on Android. it seems that the image or url is being cached somewhere so when the image is rendered again with the same URI, the same image is displayed.
i have tried the same application on IOS (the app is created using react native expo.io). the image are different as expected on IOS, it it seems to be a problem specific to Android.
is there a way to prevent android from cacheing the image and display a different image every time the Image component is rendered?
In 2020 it`s still an issue in react native (as Dishant Walia mentioned). Now best solution from github is:
add a query string after url, works for both platform
<Image
style={styles.drawerAccountImg}
source={uri: this.state.photoURL + '?' + new Date()}
/>
Somehow you have to add random string to reload image with same uri. I have fixed the same issue by adding random string in image url.
Follow this comment for more information
React native image issue

React Native: How to import local image with dynamic name

I have about 100 heroes' image on local that need to import into the listview. This is my hero.js
renderRow(hero) {
return (
<View>
<View style={styles.container}>
<Image
source={require('./img/hero/'+hero.img+'.jpg')}
style={styles.thumbnail} />
<View style={styles.rightContainer}>
<Text style={styles.title}>{hero.name}</Text>
</View>
</View>
<View style={styles.separator} />
</View>
);
After some research I know require won't allow dynamic name. I also tried uri, no error but no image either.
{{uri: './img/hero/'+hero.img+'.jpg'}}
My folder structure is like this:
Project
index.ios.js
hero.js
img
hero
What is the best way to handle this, I don't want to put images on the network.
sahrens said the following on this forum
We intentionally don't support dynamically generated image names because it makes it very hard to manage assets over time, just like how you wouldn't want to do
It looks like it can be done via uri but it will require a bit of work. You will need to add your images in xcode assets and for android under res/drawable.
Then you can get your image with <Image source={{ uri: "image" + "name" }} />
I solved this issue in one way, just post my answer here in case others interesting on how to deal with this.
I wrote a php script to read all images in my hero folder and print out in this format:
heroName: require ('./img/hero/heroName.jpg')
<?php
$dir = "./img/hero";
// Open a known directory, and proceed to read its contents
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
$images = array();
while (($file = readdir($dh)) !== false) {
$keyName = str_replace(".jpg","",$file);
print "$keyName: require('./img/hero/$file'),". "<br />";
}
closedir($dh);
}
}
?>
Then I copy the result, paste into a js file and store as object like this:
export default heroList = {
name1: require('./img/hero/name1.jpg'),
name2: require('./img/hero/name2.jpg'),
etc....
}
Finally in my hero.js file:
import heroList from './heroList';
....
source={heroList[heroName]}

Image doesn't load via url

Image object doesn't loads images via url.
<Image style={{height: 120, width: 120}} source={{uri: 'http://somedomain.com/'+this.props.icon}}/>
And if I download this image via RNFS to local directory (I've checked images downloaded correctly) and try to load then it fails:
<Image style={{height: 120, width: 120}} source={{uri: 'res/'+this.props.icon}}/>
Even if i try path with RNFS constant it doesn't works too:
<Image style={{height: 120, width: 120}} source={{uri: RNFS.DocumentDirectoryPath+'/res/'+this.props.icon}}/>
UPD
I don't know why but remote image doesn't work only sometimes (on some domains independent of http or https)
And I have made check for every local image before render:
RNFS.exists(LOGOPATH+this.props.logo).then((data)=> {
console.log(data)
})
And it returned true for every image, it means that path is correct
You can use this method in your java file
public void loadPimage(String picUrlString){
Glide.with(this).load(picUrlString).diskCacheStrategy(DiskCacheStrategy.SOURCE).into(YourImageView);
}
and call it like this
loadPimage(YourURL);
but dont forget to add compile 'com.github.bumptech.glide:glide:3.7.0' to your dependencies in Build.gradle file

Save image from URL to device with React Native

Hi as title suggests I need to save images to Android device from my CDN.
I am building app with React Native, and what I've done is that:
fetch('https://server.com/images.json').then((json) => console.log(json))
Which returns json:
{images: ["cdn.server.com/image1.jpg", "cdn.server.com/image2.jpg"]}
And now I really don't know what to do to save images to my device, because then I need to use them to open Instagram Intent (https://www.instagram.com/developer/mobile-sharing/android-intents/) and it only works if image is saved to device.
Any ideas?
I don't know react can using Java code.
I offen using this code to get image from url.
String imageCDN = json.getString("images");
ImageLoader imageLoader = new ImageLoader(this);
ImageView imgflag = (ImageView) findViewById(R.id.flag);
imageLoader.DisplayImage(imageCDN, imgflag);
But you should read this tutorial
At this code:
renderMovie(movie) {
return (
<View style={styles.container}>
<Image
source={{uri: movie.posters.thumbnail}}
style={styles.thumbnail}
/>
<View style={styles.rightContainer}>
<Text style={styles.title}>{movie.title}</Text>
<Text style={styles.year}>{movie.year}</Text>
</View>
</View>
);
}
You don't need to save image because memory leak, using ListView to clone all image in DataSource.

Categories

Resources