4

I am trying to check if the url of an image is 404 or not. The problem is that the function is returning undefined. Why is this happening?

If I console.log the status of the res it does show 404 so the if statement is being executed.

function checkImageURL(url){
 fetch(url)
    .then(res => {
    if(res.status == 404){
      console.log(res.status)
      return <Image source={require('./Images/default.png')}/>
    }else{
      return <Image source={{uri: `${url}`}}  />
   }
 })
}
jrocc
  • 1,274
  • 2
  • 18
  • 48

3 Answers3

10

you are not returning anything on error response.

add .catch and return a component or null in that. for eg

function checkImageURL(URL) {
  fetch(URL)
    .then((res) => {
      if (res.status == 404) {
        return <Image source={require('./Images/default.png')} />;
      } else {
        return <Image source={{ uri: `${url}` }} />;
      }
    })
    .catch((err) => {
      return <Image source={require('./Images/default.png')} />;
    });
}
Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
6

Actually, you don't need to check if the image response status it's not 404 to be able to display it. You just need to fetch your data and store it in your state, then check if the image can be displayed like the example below.

I am not exactly what are you trying to build but in my opinion, you should never make a request to fetch an image.

There is a defaultSource prop now.

<Image
  source={{ uri: 'https://example.com/image.png' }}
  style={{ height: 200, width: 200 }}
  defaultSource={defaultImg}
/>

Check the snack https://snack.expo.io/@abranhe/defaultimage

Abraham
  • 8,525
  • 5
  • 47
  • 53
  • 2
    This does not work. If your some-url path is not a valid image, it will show empty image instead of the defaultImg – The1993 Mar 04 '20 at 03:20
  • Agreed, this does not work, exactly as The1993 said. – instanceof Feb 18 '21 at 12:26
  • I have updated the answer and it should be working fine now – Abraham Feb 18 '21 at 18:15
  • Ahh yes this is a huge life saver. I was trying to use the on error to change the state but I was often mapping over multiple avatars so one 404 would set them all to false. I knew there was a better way. – Kyle J Jun 25 '22 at 02:59
6

Although the selected answer solves the problem in question, the overarching problem here I notice is the way the OP is handling an image uri that returns a 404. If your intention is to have a fallback image in the case that an image's uri is invalid for whatever reason (any 400ish response), I'd recommend leveraging the onError <Image/> prop.

I have an <Avatar/> component that uses this prop:

import { Image, ImageStyle } from 'react-native'
import React, { useState } from 'react'
import { avatarPlaceholder } from '../../assets/images'

interface Props {
  avatar: string;
  style: ImageStyle;
}

const Avatar = React.memo((props: Props) => {
  const [valid, setValid] = useState(true)
  const { avatar, style } = props

  return (
    <Image
      onError={() => setValid(false)}
      style={[{
        resizeMode: "cover",
        borderRadius: 1000,
      }, style]}
      source={{ uri: valid ? avatar : avatarPlaceholder }}
    />
  )
})

export default Avatar

Happy coding!

Ethan Naluz
  • 311
  • 5
  • 4