specifying image src as dynamic state variable in React Native - image

I want to load an image in react native. I have gone through many posts but almost every post talks about specifying static / local url’s of image as a source. However , I want to specify it as
src= {this.state.url}
Where this.state.url is assigned a dynamic url (from google images )within the code.
Is it possible ?

Try the Tholle answer
Image source={{ uri: 'https://example.com/image.png' }}
But in your render() make it changes as so :
render(){
var image = ( <Image source={{this.state.url}} /> );
return(
<View>
{image}
</View>
)
}
So whenever your component state will change, render will be called with the updated url I think

Related

Is there a way i can download an image with text appended on it with react native

Im building a react-native app and the screen so far loads an image from a uri into a BackgroundImage and there is also some text loading on top of the image, please see the attached image:
So what i want is to get this image and text downloaded to the device, merge them if you will?
Any suggestions are welcome..
Thanks
I would recommend you to use the ViewShot component from here.
Here's an example of how you would be able to integrate it with your project (keep in mind this uses the ES6 arrow function syntax):
class CaptureImage extends Component {
capturePic = () => {
this.refs.viewShot.capture().then(uri => {
console.log("Path to the image: ", uri); // do what you want with the url
})
};
render() {
return (
<View
<ViewShot ref="viewShot">
// your background image components go here (the image with the text you want to capture)
</ViewShot>
// rest of your code goes here
<Button onClick= {() => capturePic()} /> // button just for demonstration purpose
</View>
);
}
}
Hope you understood :)

React Native image source not showing up

I am trying to retrieve image data for an <Image> component in React Native.
The problem is the API I'm getting data from sometimes doesn't have an image source. So I have this code to check if the source.uri is not empty and if it is the image will be replaced by one I have saved in the project. The problem is that when the source.uri is null my image doesn't appear and instead there's a black space.
import noImage from '../assets/noImage.jpg'
render()
{
return (
<Image
style={{ width: SCREEN_WIDTH / 3, height: 13 }}
borderRadius="10"
resizeMode="stretch"
source={item.restaurant.thumb ? { uri: item.restaurant.thumb } : { noImage }} />
);
}
You could probably try this.
render(){
return(
<Image style={{width:SCREEN_WIDTH/3, height:130}} borderRadius="10" resizeMode="stretch" source={item.restaurant.thumb ? {uri: item.restaurant.thumb} : require('../assets/noImage.jpg')}}/>
)}
+require('../assets/noImage.jpg')
-import noImage from '../assets/noImage.jpg'
-{noImage}
I guess your "noImage" is not a web link, so you need to use require
source={item.restaurant.thumb ? {uri: item.restaurant.thumb} : require('path/noImage.png'})}

Conditionally Render Images in React Native

I have been trying to render an image based on a condition. Currently I have a list and it is empty at the start of the app, after a certain event, this list gets populated with a string, and the listLength variable changes from 0(false-ish) to 1(true-ish). I have tried passing both the list length and the list itself as a conditional for the image source using the ternary operator. Can someone please help me figure out what is going on.
let connect_logs = []
let connect_line_length = connectLogs.length
return (
<View style={styles.container}>
<Image
source={
connect_line_length ? require('../assets/images/connect_line.png') :
require('../assets/images/no_line.png')
}
style={styles.lineImage}
/>
)
Firstly you should keep in mind that (almost all the time) if you want to change the UI of your app (re-render a component) on the basis of some variable/object/list etc, then that variable/object/list etc. should be declared as a state variable.
So I would suggest you to initialize your list inside you component's state like this:
state = {
connect_logs: [],
}
Then whenever you want to add update your list you should perform this by calling setState() to re-render your UI to reflect the latest changes, for example:
const updatedList = ['item1', 'item2', 'item3']; //dummy values
this.setState({connect_logs: updatedList}); //update state to change UI
And now you should apply your condition on this.state.connect_logs to dynamically change the source of your image like this:
return (
<View style={styles.container}>
<Image
source={
this.state.connect_logs.length>0 ?
require('../assets/images/connect_line.png') :
require('../assets/images/no_line.png')
}
style={styles.lineImage}
/>
</View>
)
I see that the View tag does not have a close tag? I think this could not be the issue but just try closing the tag and also just for testing try this
let connect_logs = []
let connect_line_length = connectLogs.length
return (
<View style={styles.container}>
<Image source={connect_line_length ? '1' : '0'}
style={styles.lineImage} />
</View>
)

React Native: How to implement carousel of images with zoom in FlatList component?

I use a FlatList component for images grid because it have a good performance:
<FlatList
data={photos}
columnWrapperStyle={styles.listColumn}
numColumns={4}
renderItem={photo => this.renderPhoto(photo)}
/>
For now renderPhoto func return a new FastImage component (i use it because it have a cool caching feature)
<FastImage
resizeMode={FastImage.resizeMode.cover}
source={{uri: photo.src}}
/>
In the end I have something like this:
But now I want to have a very familiar possibility. Tap on the image will start the animation after which the image will be stretched to the full width of the screen.
After that, the user can do the following:
Swipe left/right to see prev/next images from the FlatList
Zoom current image
Tap on image to show/hide control elements (footer and header)
Swipe up/down for closing carousel and return to the grid component
It might look something like this:
So, whats a problem?
All existing carousel solutions are a wrapper for an image collection. But I cant pass wrapper component inside FlatList.
I could not find a ready-made component for solving such a common problem.
There are some that I try to combine (Lightbox, Carousel). But this solution will greatly affect performance. (I need to load the entire collection of images from the FlatList into the carousel component) In addition, such solutions usually have problems with animation.
So I'm wondering if there really is no react-native solution for such a popular image view mechanics?
Perhaps it is worth making a native module on the swift/objc (FlatList of images with carousel modal)?
Actually is possible with the elements that you have.
First you have the carousel (react-native-looped-carousel):
const activeProps = {
resizeMode: 'contain',
flex: 1,
width: null
};
const { height, width } = Dimensions.get('window');
const renderCarousel = (album, currentPage) => (
<Carousel style={{ width, height }} currentPage={currentPage} autoplay={false}>
{album.map(image => (
<FastImage
style={{ flex: 1 }}
resizeMode={FastImage.resizeMode.contain}
source={{ uri: image.uri }}
key={image.uri}
/>))
}
</Carousel>
);
Then FastImage (react-native-fast-image) with the lightbox (react-native-lightbox):
LightImage = (props) => {
const currentPage = this.items.findIndex(x => x.uri === props.source.uri);
return (
<Lightbox
activeProps={activeProps}
renderContent={() => renderCarousel(this.items, currentPage)}
>
<FastImage {...props} />
</Lightbox>
);
}
Now you can use your renderItem with the component for the FastImage and Lightbox
<FlatList
data={this.items}
columnWrapperStyle={styles.listColumn}
numColumns={4}
renderItem={photo => this.LightImage(photo)}
/>
I've copied part of my code, so it won't work with just copy and paste. If you have any question feel free to ask!
There's only one problem with this implementation that if you rotate the device the layout breaks

React Native: Render Image from props [duplicate]

I'm currently building a test app using React Native. The Image module thus far has been working fine.
For example, if I had an image named avatar, the below code snippet works fine.
<Image source={require('image!avatar')} />
But if I change it to a dynamic string, I get
<Image source={require('image!' + 'avatar')} />
I get the error:
Requiring unknown module "image!avatar". If you are sure the module is there, try restarting the packager.
Obviously, this is a contrived example, but dynamic image names are important. Does React Native not support dynamic image names?
This is covered in the documentation under the section "Static Resources":
The only allowed way to refer to an image in the bundle is to literally write require('image!name-of-the-asset') in the source.
// GOOD
<Image source={require('image!my-icon')} />
// BAD
var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
<Image source={require('image!' + icon)} />
// GOOD
var icon = this.props.active ? require('image!my-icon-active') : require('image!my-icon-inactive');
<Image source={icon} />
However you also need to remember to add your images to an xcassets bundle in your app in Xcode, though it seems from your comment you've done that already.
http://facebook.github.io/react-native/docs/image.html#adding-static-resources-to-your-app-using-images-xcassets
This worked for me :
I made a custom image component which takes in a boolean to check if the image is from web or is being passed from a local folder.
// In index.ios.js after importing the component
<CustomImage fromWeb={false} imageName={require('./images/logo.png')}/>
// In CustomImage.js which is my image component
<Image style={styles.image} source={this.props.imageName} />
If you see the code, instead of using one of these:
// NOTE: Neither of these will work
source={require('../images/'+imageName)}
var imageName = require('../images/'+imageName)
I'm just sending the entire require('./images/logo.png') as a prop. It works!
RELEVANT IF YOU HAVE KNOWN IMAGES (URLS):
The way I hacked my way through this problem:
I created a file with an object that stored the image and the name of the image:
export const ANIMAL_IMAGES = {
dog: {
imgName: 'Dog',
uri: require('path/to/local/image')
},
cat: {
imgName: 'Cat on a Boat',
uri: require('path/to/local/image')
}
}
Then I imported the object into the component where I want to use it and just do my conditional rendering like so:
import { ANIMAL_IMAGES } from 'path/to/images/object';
let imgSource = null;
if (condition === 'cat') {
imgSource = ANIMAL_IMAGES.cat.uri;
}
<Image source={imgSource} />
I know it is not the most efficient way but it is definitely a workaround.
Hope it helps!
If you're looking for a way to create a list by looping through a JSON array of your images and descriptions for example, this will work for you.
Create a file (to hold our JSON database) e.g ProfilesDB.js:
const Profiles = [
{
id: '1',
name: 'Peter Parker',
src: require('../images/user1.png'),
age: '70',
},
{
id: '2',
name: 'Barack Obama',
src: require('../images/user2.png'),
age: '19',
},
{
id: '3',
name: 'Hilary Clinton',
src: require('../images/user3.png'),
age: '50',
},
];
export default Profiles;
Then import the data in our component and loop through the list using a FlatList:
import Profiles from './ProfilesDB.js';
<FlatList
data={Profiles}
keyExtractor={(item, index) => item.id}
renderItem={({item}) => (
<View>
<Image source={item.src} />
<Text>{item.name}</Text>
</View>
)}
/>
Good luck!
As the React Native Documentation says, all your images sources needs to be loaded before compiling your bundle
So another way you can use dynamic images it's using a switch statement. Let's say you want to display a different avatar for a different character, you can do something like this:
class App extends Component {
state = { avatar: "" }
get avatarImage() {
switch (this.state.avatar) {
case "spiderman":
return require('./spiderman.png');
case "batman":
return require('./batman.png');
case "hulk":
return require('./hulk.png');
default:
return require('./no-image.png');
}
}
render() {
return <Image source={this.avatarImage} />
}
}
Check the snack: https://snack.expo.io/#abranhe/dynamic-images
Also, remember if your image it's online you don't have any problems, you can do:
let superhero = "spiderman";
<Image source={{ uri: `https://some-website.online/${superhero}.png` }} />
First, create a file with image required - React native images must be loaded this way.
assets/index.js
export const friendsandfoe = require('./friends-and-foe.png');
export const lifeanddeath = require('./life-and-death.png');
export const homeandgarden = require('./home-and-garden.png');
Now import all your assets
App.js
import * as All from '../../assets';
You can now use your image as an interpolated value where imageValue (coming in from backend) is the same as named local file ie: 'homeandgarden':
<Image style={styles.image} source={All[`${imageValue}`]}></Image>
Important Part here:
We cannot concat the image name inside the require like [require('item'+vairable+'.png')]
Step 1: We create a ImageCollection.js file with the following collection of image properties
ImageCollection.js
================================
export default images={
"1": require("./item1.png"),
"2": require("./item2.png"),
"3": require("./item3.png"),
"4": require("./item4.png"),
"5": require("./item5.png")
}
Step 2: Import image in your app and manipulate as necessary
class ListRepoApp extends Component {
renderItem = ({item }) => (
<View style={styles.item}>
<Text>Item number :{item}</Text>
<Image source={Images[item]}/>
</View>
);
render () {
const data = ["1","2","3","4","5"]
return (
<FlatList data={data} renderItem={this.renderItem}/>
)
}
}
export default ListRepoApp;
If you want a detailed explanation you could follow the link below
Visit https://www.thelearninguy.com/react-native-require-image-using-dynamic-names
Courtesy : https://www.thelearninguy.com
you can use
<Image source={{uri: 'imagename'}} style={{width: 40, height: 40}} />
to show image.
from:
https://facebook.github.io/react-native/docs/images.html#images-from-hybrid-app-s-resources
import React, { Component } from 'react';
import { Image } from 'react-native';
class Images extends Component {
constructor(props) {
super(props);
this.state = {
images: {
'./assets/RetailerLogo/1.jpg': require('../../../assets/RetailerLogo/1.jpg'),
'./assets/RetailerLogo/2.jpg': require('../../../assets/RetailerLogo/2.jpg'),
'./assets/RetailerLogo/3.jpg': require('../../../assets/RetailerLogo/3.jpg')
}
}
}
render() {
const { images } = this.state
return (
<View>
<Image
resizeMode="contain"
source={ images['assets/RetailerLogo/1.jpg'] }
style={styles.itemImg}
/>
</View>
)}
}
To dynamic image using require
this.state={
//defualt image
newimage: require('../../../src/assets/group/kids_room3.png'),
randomImages=[
{
image:require('../../../src/assets/group/kids_room1.png')
},
{
image:require('../../../src/assets/group/kids_room2.png')
}
,
{
image:require('../../../src/assets/group/kids_room3.png')
}
]
}
when press the button-(i select image random number betwenn 0-2))
let setImage=>(){
//set new dynamic image
this.setState({newimage:this.state.randomImages[Math.floor(Math.random() * 3)];
})
}
view
<Image
style={{ width: 30, height: 30 ,zIndex: 500 }}
source={this.state.newimage}
/>
I know this is old but I'm going to add this here as I've found this question, whilst searching for a solution. The docs allow for a uri: 'Network Image'
https://facebook.github.io/react-native/docs/images#network-images
For me I got images working dynamically with this
<Image source={{uri: image}} />
<StyledInput text="NAME" imgUri={require('../assets/userIcon.png')} ></StyledInput>
<Image
source={this.props.imgUri}
style={{
height: 30,
width: 30,
resizeMode: 'contain',
}}
/>
in my case i tried so much but finally it work StyledInput component name
image inside the StyledInput if you still not understand let me know
Say if you have an application that has similar functionality as that of mine. Where your app is mostly offline and you want to render the Images one after the other. Then below is the approach that worked for me in React Native version 0.60.
First create a folder named Resources/Images and place all your images there.
Now create a file named Index.js (at Resources/Images) which is responsible for Indexing all the images in the Resources/Images folder.
const Images = {
'image1': require('./1.png'),
'image2': require('./2.png'),
'image3': require('./3.png')
}
Now create a Component named ImageView in your choice of folder. One can create functional, class or constant component. I have used the Const component. This file is responsible for returning the Image depending on the Index.
import React from 'react';
import { Image, Dimensions } from 'react-native';
import Images from './Index';
const ImageView = ({ index }) => {
return (
<Image
source={Images['image' + index]}
/>
)
}
export default ImageView;
Now from the component wherever you want to render the Static Images dynamically, just use the ImageView component and pass the index.
< ImageView index={this.qno + 1} />
Create a constant where you save the image path including require, then in source put the name of that constant.
const image = condition ? require("../img/image1.png") : require('../img/image2.png');
<Image source={image} />
Here is a simple and truly dynamic solution to the problem if you have a bigger no of files.
[Won't work for Expo Managed]
Although the question is old I think this is the simpler solution and might be helpful. But I beg a pardon for any terminological mistakes, correct me please if I do any.
INSTEAD OF USING REQUIRE WE CAN USE THE URI WITH NATIVE APP ASSETS FOR ANDROID (AND/OR iOS). HERE WE WILL DISCUSS ABOUT ANDROID ONLY
URI can easily be manipulated as per the requirement but normally it's used for network/remote assets only but works for local and native assets too. Whereas require can not be used for dynamic file names and dirs
STEPS
Open android/app/src/main/assets folder from your App.js or index.js containing directory, if the assets folder doesn't exist create one.
Make a folder named images or any NAME of your choice inside assets, and paste all the images there.
Create a file named react-native.config.js in the main app folder containing App.js or index.js.
Add these lines to the new js file:
module.exports = {
project: {
ios: {},
android: {},
},
assets: ['./assets/YOUR_FOLDER_NAME/'],
};
at the place of YOUR_FOLDER_NAME use the newly created folder's name images or any given NAME
Now run npx react-native link in your terminal from main app folder, this will link/add the assets folder in the android bundle. Then rebuild the debug app.
From now on you can access all the files from inside android/app/src/main/assets in your react-native app.
For example:
<Image
style={styles.ImageStyle}
source={{ uri: 'asset:/YOUR_FOLDER_NAME/img' + Math.floor(Math.random() * 100) + '.png' }}
/>
You should use an object for that.
For example, let's say that I've made an AJAX request to an API and it returns an image link that I'll save to state as imageLink:
source={{uri: this.state.imageLink}}

Resources