0

I'm creating a small application with React Native that has a local SQLite database for storing images but having trouble rendering my array of images (fetched from the local database and stored in the local state).

Before I was rendered by mapping the data and that worked fine.

  state = {
    items:[when the user uses the app this array fills with images],
  };
<ScrollView>
        {items.map(({ id, value }) => (
          <TouchableOpacity onPress={this.deletePhoto}
            key={id}>
            <Image source={{ uri: value }} style={{ width: null, height: 400 }} />
          </TouchableOpacity>

        ))}
      </ScrollView>
    );
  }

But now I would like to go a step further and render the data in a FlatList with my choice of formatting (a grid). Although I can get the FlatList to render the number of images within the array, I can't get the actual image to show. I'm not sure how to pass the data successfully?

  renderItem = ({ id, value }) => {
  const { items } = this.state;
  if (items.empty === true) {
    return <View style={[styles.item, styles.itemInvisible]} />;
  }
  return (
    <TouchableOpacity style={styles.item} onPress={this.deletePhoto} key={id}>
            <Image source={{ uri: value }} style={{ width: null, height: 400 }} />
    </TouchableOpacity>
  );
  };

For context, this is the creation of the 'items' SQL Table with the 'id' and 'value' attributes:

componentDidMount() {
    db.transaction(tx => {
      tx.executeSql(
        'create table if not exists items (id integer primary key not null, value text);'
      );
    });
  }

I guess the question is, how do I pass/access the attributes of the items array into a functional component?

Update:

https://ibb.co/hMY1qBy (What I'm getting - e.g DB Entry creating a View but no image rendering) https://ibb.co/RN4rqyK (What I'm getting from the answer below)

James Stirrat
  • 101
  • 2
  • 12

2 Answers2

1

After getting a reproducible code from your repo that you shared I manage to render the images in the list.

After rendering images in the list

Here is your renderItem function

renderItem = ({ item }) => {
  const { items } = this.state;
  if (items.empty === true) {
    return <View style={[styles.item, styles.itemInvisible]} />;
  }
  return (
    <TouchableOpacity style={styles.item} onPress={this.deletePhoto} key={item.id}>
            <Image source={{ uri: item.value }} style={{ width: 400, height: 120 }} />
    </TouchableOpacity>
  );
  };

You have to get the item from your params of the renderItem function as well you have to pass width to image for rendering, The above code is working fine.

Waheed Akhtar
  • 3,110
  • 1
  • 16
  • 30
  • Great! I understand the logic. How does the FlatList look? As I'm still not getting a rendering of the image - so I assume missing something there. – James Stirrat Jun 01 '20 at 10:32
  • I have shown you the code and the list above, If still not work then I can push the code in your repo in a separate branch. – Waheed Akhtar Jun 01 '20 at 14:21
  • Got em' - Thank you Waheed. – James Stirrat Jun 02 '20 at 11:02
  • Yes, it works almost completely, it just isn't rendering the empty blocks (the top part of the ```renderItem``` function. So figuring that out – James Stirrat Jun 02 '20 at 15:34
  • try it, and if not work let me know, I will also render the empty blocks too. – Waheed Akhtar Jun 02 '20 at 15:40
  • Understand how to fix it (I believe) but struggling to declare the length of the items array so that the function knows how many empty blocks to render! Essentially the same problem as before (passing through the value of each item) but before you solved it by passing through item as a param with renderItem. Would be fantastic to solve it – James Stirrat Jun 02 '20 at 17:24
  • I didn't get you, as my understanding you want to render empty block but what is the use case to render the empty block? – Waheed Akhtar Jun 02 '20 at 17:43
  • Because in the FlatList we're looking to render 3 images in each row, or to have 3 columns. So the problem is that when you have a number of posts that are not a multiple of three, eg. 7. The 7th post takes up a full row and 100% width of the screen. I can kind of fix this by formatting the containing view or image to be one third of the screen (which I have done) but then the image places itself awkwardly. By rendering empty blocks, we can make sure each post only takes up a third of the screen and will be placed underneath a column – James Stirrat Jun 02 '20 at 17:55
  • https://www.bootdey.com/files/ReactNative/154592422414559588_5c24ee802ad8a.png - is a good example – James Stirrat Jun 02 '20 at 17:56
  • Now i got it, Will you please share some example array which you are passing to your list. – Waheed Akhtar Jun 02 '20 at 18:16
  • It's exactly the same array/repo you used before actually. There's a ```formatItems``` function that takes all the same arguments and should output the right number of empty blocks to be rendered by ```renderItem```. I'm now calling that function in ```async componentDidMount()``` and trying to figure out how to push the correct amount of empty blocks to the ```items``` array to be rendered – James Stirrat Jun 02 '20 at 18:55
  • 1
    @JamesStirrat Okay, I will look into this by tomorrow. – Waheed Akhtar Jun 02 '20 at 18:56
  • Thanks Waheed - much appreciated! – James Stirrat Jun 03 '20 at 22:42
0

The flatlist renderItem prop gets a argument with multiple properties the main ones will be item and index which are commonly used to access the item in of the row you can use item like below

<FlatList
        data={items}
        renderItem={({ item }) => (
          <TouchableOpacity style={styles.item} onPress={this.deletePhoto} key={item.id}>
            <Image source={{ uri: item.value }} style={{ width: null, height: 400 }} />
    </TouchableOpacity>
        )}
        keyExtractor={item => item.id}
      />
Guruparan Giritharan
  • 15,660
  • 4
  • 27
  • 50