Diana
Diana

Reputation: 213

Why aren't images showing in React Native? Failed prop type: Invalid prop `source` supplied to `Image`

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')

enter image description here

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

Answers (2)

Himmels DJ
Himmels DJ

Reputation: 445

There are two ways of displaying images in React js depending on what you want to acheive.

  1. The first one is when you want to display the images manually, then import the image from wherever it is located like you did to the star image inside the assets folder: import star from '../../../../assets/star'; You can the use it straight in the same component by doing: <img src={image} .. />
  1. 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

Sahesh
Sahesh

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

Related Questions