Reputation: 213
How can I import the images from the assets folder and not use images from the internet through url?
Why is the Icon not showing?
I am studying React native trying to create a small application that shows the businesses of a city.
I must say that I am using "styled-components / native"
for the styles, and have put them in separate files, as you will see that the components are not correctly named, but this works fine.
I have created an object in which the details of each business are indicated:
name, address, icon of the type of business it is, business image, image to know if the business is closed or open.
Then, I try to show these details in a Card and send it to another page of the app where the different businesses that I add through a FlatList
will be shown.
The problem is that I don't know how to add the images from the assets folder in the object, I don't know the correct way to import them, the exact syntax to bring the images to the object and then call them within the Card component, for example:
image = require ('../../../../ assets / logos.jpg')
Since I can't find a way to import the images from the assets folder, I have resorted to importing them from a Url, and then calling them with URIs. But either because of the internet connection or for another reason, the images are not displayed correctly in the application. The picture.
photos = ["https://cdn.pixabay.com/photo/2015/09/09/19/56/office-932926_1280.jpg"],
which I call with the method.
<StoreCardCover
key = {name}
resizeMethod = 'scale'
source = {{uri: photos [0]}}
/>
if that is shown, but nevertheless the icon, is not shown in the application:
icon = "https://img.icons8.com/material-two-tone/384/000000/espresso-cup--v2.png",
<Icon source = {{uri: icon}} />
I have looked for information and I have tried to import the images from assets in various ways, without success
icon = {image: require ('../../../../ assets / logos.jpg')},
photos = ["https://cms-assets.tutsplus.com/cdn-cgi/image/width=360/uploads/users/1125/posts/30546/preview_image/RN.jpg"],
I get different errors:
ExceptionsManager.js: 180 Warning: Failed prop type: Invalid prop `source` supplied to` Image`.
at Image
console.error: JSON value '{
image = 1;
} 'of type NSMutableDictionary cannot be converted to NSString
reactConsoleErrorHandler
ExceptionsManager.js: 237: 33
overrideMethod
backend.js: 2139: 25
registerError
LogBox.js: 147: 8
errorImpl
LogBox.js: 58: 21
console.error
LogBox.js: 32: 13
logToConsole
RCTLog.js: 47: 4
logIfNoNativeHook
RCTLog.js: 30: 6
__callFunction
MessageQueue.js: 414: 26
__guard $ argument_0
MessageQueue.js: 113: 11
__guard
MessageQueue.js: 365: 8
What is the correct way to import images into an object from a folder in the App to be able to display them in different parts of the App?
I show the files for you to judge my mistakes
File StoreInfo.js
import React from 'react'
import { StyleSheet, Image } from 'react-native'
import { SvgXml } from 'react-native-svg'
import star from '../../../../assets/star'
import closed from '../../../../assets/closed'
import {
StoreCard,
StoreCardCover,
Title,
Address,
Info,
Rating,
Section,
SectionEnd,
Icon
} from './StoreInfoStyles'
export const StoreInfo = ({ store = {} }) => {
const {
name = "Online Company",
icon= {image: require('../../../../assets/logos.jpg')},
photos = ["https://cms-assets.tutsplus.com/cdn-cgi/image/width=360/uploads/users/1125/posts/30546/preview_image/RN.jpg"],
//icon = "https://img.icons8.com/material-two-tone/384/000000/espresso-cup--v2.png",
//photos = ["https://cdn.pixabay.com/photo/2015/09/09/19/56/office-932926_1280.jpg"],
address = "Charcos Enbarrados, 6 Ninguna Parte 04593",
rating = 4,
isClosed = true,
} = store
const ratingArray = Array.from(new Array(Math.floor(rating)))
return (
<StoreCard
elevation={5}
>
<StoreCardCover
key={name}
resizeMethod='scale'
source={{ uri: photos[0] }}
/>
<Info>
<Title> {name} </Title>
<Section>
<Rating
style={styles.rating}
>
{ratingArray.map(() => (
<SvgXml xml={star} width={30} height={30} />
))}
</Rating>
<SectionEnd>
{isClosed && <SvgXml xml={closed} width={40} height={40} />}
<Icon source={{ uri: icon }} />
</SectionEnd>
</Section>
<Address> {address} </Address>
</Info>
</StoreCard>
)
}
const styles = StyleSheet.create({
rating: {
paddingLeft: 20
}
})
File StorePantalla.js
import React from 'react'
import { View, SafeAreaView, FlatList } from 'react-native'
import { Searchbar } from 'react-native-paper'
import { StoreInfo } from '../componentStore/StoreInfo'
import styled from 'styled-components/native'
const SafeArea = styled(SafeAreaView)`
flex:1;
`
const BarSearch = styled(View)`
padding: ${(props) => props.theme.space[3]}
`
const StoreList = styled(FlatList).attrs({
contentContainerStyle: {
paddingHorizontal: 16,
paddingTop: 8,
paddingBottom: 16 }
})
`
`
export default function StorePantalla() {
return (
<SafeArea>
<BarSearch>
<Searchbar
placeholder="Search"
/>
</BarSearch>
<StoreList
data={[{ name: 1 }, { name: 2 }, { name: 3 }]}
renderItem={() => <StoreInfo />}
keyExtractor={(item) => item.name}
/>
</SafeArea>
)
}
Fil StoreInfoStyles.js
import styled from "styled-components/native"
import { View, Text, Image } from 'react-native'
import { Card } from 'react-native-paper'
export const StoreCard = styled(Card)`
background-color: ${(props) => props.theme.colors.bg.secondary}
margin-bottom: ${(props) => props.theme.space[4]}
`
export const StoreCardCover = styled(Card.Cover)`
padding: ${(props) => props.theme.space[4]}
background-color: ${(props) => props.theme.colors.bg.primary}
`
export const Title = styled.Text`
font-family: ${(props) => props.theme.fonts.heading}
padding-left: ${(props) => props.theme.space[3]}
padding-bottom: ${(props) => props.theme.space[1]}
fontSize: ${(props) => props.theme.sizes[2]}
color: ${(props) => props.theme.colors.text.primary}
`
export const Address = styled(Text)`
font-family: ${(props) => props.theme.fonts.body}
padding-left: ${(props) => props.theme.space[3]}
padding-bottom: ${(props) => props.theme.space[4]}
`
export const Info = styled(View)`
padding-right: ${(props) => props.theme.space[2]}
padding-left: ${(props) => props.theme.space[3]}
padding-bottom: ${(props) => props.theme.space[3]}
`
export const Rating = styled(View)`
flex-direction: row;
padding-left: ${(props) => props.theme.space[2]}
padding-bottom: ${(props) => props.theme.space[2]}
`
export const Section = styled(View)`
flex-direction: row;
align-items: center;
`
export const SectionEnd = styled(View)`
flex: 1;
flex-direction: row;
justify-content: flex-end;
`
export const Icon = styled(Image)`
width= 35px;
height= 35px;
margin-left: ${(props) => props.theme.space[3]}
`
Upvotes: 0
Views: 1273
Reputation: 445
There are two ways of displaying images in React js depending on what you want to acheive.
The second way is when you don't display the images manually but dynamically, by image props passed from a component to another, or images' name fetched from a flatList. For that you necessary need to have the images inside the public folder of your React application, or inside a folder located in the public folder of your application, and then you can use its props in the component making sure the path is correct from the child component. Then you can use the props at your leisure:
const Galery = (props) => (
<div>
<p>{props.title}</p>
<div>{props.image}</div>
</div>
);
The restriction with passing image as props in react is that the images have to be located inside the public folder and not in the assets folder, because React uses Webpack.
For the sake of completness, it seems like you wanted to use Icons, why don't you just import them from the Icons' library? Unless they are personal Icons. The answer is for dynamically load images (personal Icons included) from your project's folders to web page with React. I Hope it helps.
Upvotes: 0
Reputation: 885
Please change the section end code with this and check whether you can see the image.
<SectionEnd>
<Image style={{width: 40, height: 40}} source={{uri: "https://cdn.pixabay.com/photo/2015/09/09/19/56/office-932926_1280.jpg"}}/>
</SectionEnd>
Also make sure you have put right permission in Android Manifest.
<uses-permission android:name="android.permission.INTERNET" />
Also in AndroidManifest add the following in application section.
<application
android:usesCleartextTraffic="true"
Upvotes: 1