4
votes

I'm using FlatList to render multiple Images on the Screen. I want to render placeholder Image when item.img is null (items are fetched from react-redux).

Problems:

  1. I want to use placeholder image using 'require'. And it's using single curly brace. <Image source={ require('../assets/images/robot-prod.png') } style={styles.palceholderImage}/>. While normal Image rendering use two curly braces {{uri: item.img}}.

  2. Should I inline if(item.img) operator?

Here is _renderItem function.

 _renderItem = ({item}) => {
    let imgUrl = item.img;

    return (
      <TouchableWithoutFeedback
        onPress={() => this._handleCategoryPress(item.id)}>
        <Image
          key={item.id}
          source={{uri: item.img}}
          style={styles.rowImage}
          resizeMode="cover"
        />
      </TouchableWithoutFeedback>
    );
  }

This is API response

[
    {
        "id": 1,
        "name": "Gym",
        "image": "www.aws.blahblahblah"
    },
    {
        "id": 2,
        "name": "School",
        "image": null
    },
    {
        "id": 3,
        "name": "hollymo",
        "image": "www.aws.blahblahblah"
    },

Thanks

4
Are you using Redux? - Andrew

4 Answers

2
votes

You're looking for a full React component. An easy way of controlling rendering based on a completed API call is to use it as a promise and .then using this.setState If you're well versed in promises:

apiPromise = () => new Promise((resolve, reject)=> {
  apiData = myApiCall()
  resolve(apiData)
}

class StuffToRender extends Component {
constructor(props) {
  super(props)
  this.state = {
    loaded: false
  }
}
componentWillMount() {
  apiPromise().then (() => {
    this.setState({loaded: true})
  })
}

render() {
  return (
    <div>
      {this.state.loaded ? myContent : myContentWhileLoading}
    </div>
  )
}
}

Also, as a side note, the error you received from the other user's solution has nothing to do with the API/loading logic. It's the fact that you tried to return more than 1 html or component element:

render() {
  return (
    <div>
      stuff
    </div>
    <div>
      stuff2
    </div>
  ) //two sets of div elements expose
}

Here you are render 2 sets of items. This is what 'multiple children' means. But it's an easy fix. Just wrap the items in one single, larger container.

render() {
  return (
    <div>
      <div>
        stuff
      </div>
      <div>
        stuff2
      </div>
    </div>
  ) //everything wrapped into one single div
}
2
votes

Try this

       item.image &&      
        <Image
          key={item.id}
          source={{uri: item.img}}
          style={styles.rowImage}
          resizeMode="cover"
        />

       !item.image &&      
        <Image
          key={item.id}
          source={require('../assets/images/robot-prod.png')}
          style={styles.palceholderImage}
          resizeMode="cover"
        />
1
votes

We can handle it better in react native by following approach.

As, base64 images render in react native out of the box.

So for your case,

  1. Get the base64 data for your placeholder image.

  2. In your component,

    const placeholderBase64image = "data:image/png;base64 [yourbase64imagedata]"

  3. Inside View, use it as:

    <Image source={{ uri: yourImageUri ? yourImageUri : placeholderBase64image }}/>

0
votes

add place holder image in react native Image. use defaultSource tag

<Image source={{ uri: require('../images/dummy.png')}} 
            style={styles.itemImage}
            defaultSource={images.dummy} />