TheNewbie
TheNewbie

Reputation: 353

React Native: How to make Listview with with local images

I made an album that looks sort of like this:

<ScrollView>   
  <Image1 
     <Text1>
        smth
     </Text1>    />

  <Image2
     <Text2>
        smthElse
     </Text2>    />' ... and so on 20 times.

I have 5 albums, which I access with tabs on top. The problem is that sometimes when I switch between the tabs, some images are blank and don't load. The images are all required like this:

source={require('../assets/Image1.png')}

I want them to be required from the app and not via uri.

I thought the problem is because of the memory and on weaker phones it's possible that they don't always load, because I use a ScrollView and it loads all the images at once. I read that a ListView quite solve my problem, but I can't figure out how to make a ListView that renders 20 specific images with a specific text for each one.

If anyone can give me some clues it would be much appreciated.

Thank you !

Upvotes: 0

Views: 6391

Answers (2)

JLONG
JLONG

Reputation: 805

In order to use <ListView> You can require all the images on your .js file. On the top of your .js file you can do is

index.js

import React, { Component } from 'react';
import {Listview} from 'react-native'; //Import your other imports ofcourse

// Require all your images here
const image1 = require('../assets/Image1.png')
const image2 = require('../assets/Image2.png')

//.. And so on
export default class ClassName extends Component{
//...
}

Next is create an array object and add it to your constructor on your index.js like so

index.js

import React, { Component } from 'react';
import {Listview} from 'react-native'; //Import your other imports ofcourse

// Require all your images here
const image1 = require('../assets/Image1.png')
const image2 = require('../assets/Image2.png')

var data = [{title:"You image title", image: image1}, {title:"Your Image title",image: image2}]

export default class ClassName extends Component{
   constructor(props) {
     super(props);
     const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
     this.state = {
       dataSource: ds.cloneWithRows(data),
     };
  }
}

Next Create a Row.js

Row.js

import React from 'react'
import { StyleSheet, Dimensions, Platform, Image, View, Text } from 'react-native';
const Row = (props) => (
  <View style={{flex:1, flexDirection: 'row'}}> //Don't forget this
    <Image source={props.image}>
      <Text>{props.title}</Text> 
    </Image>
  </View>
)

export default Row

Lastly Import your Row.js file on your index.js and add the <ListView> on your render()

index.js

import React, { Component } from 'react';
import {View,Listview} from 'react-native'; //Import your other imports ofcourse
import Row from './Row'; //If it's on the same folder

// Require all your images here
const image1 = require('../assets/Image1.png')
const image2 = require('../assets/Image2.png')

var data = [{title:"You image title", image: image1}, {title:"Your Image title",image: image2}]

export default class ClassName extends Component{
   constructor(props) {
     super(props);
     const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
     this.state = {
       dataSource: ds.cloneWithRows(data),
     };
  }
  render(){
     <View>
       <ListView
         style={{flex:1}} //Don't forget this too
         dataSource={this.state.dataSource}
         renderRow={(data) => <Row {...data} />}
       />
     </View>
  }
}

Hope this helps you. Cheers!

Upvotes: 1

martwetzels
martwetzels

Reputation: 437

In response to your question how to use a ListView to render 20 images. We are using a SectionList for rendering multiple photos. I will share the snippets below to get you started.

SectionList

<SectionList
    contentContainerStyle={styles.sectionListContainer}
    renderItem={this.renderItem}
    renderSectionHeader={this.renderHeader}
    sections={this.state.ImageData}
/>

this.renderItem

renderItem(data) {
    return (
        <View key={data.item.key} style={{ flex: 1 }}>
            <View style={{ flex: 1, flexDirection: "row", flexWrap: "wrap" }}>
                <Image
                    style={styles.foodPhoto}
                    source={{ uri: `data:image/jpg;base64,${data.item.photo}`}}
                />
            </View>
        </View>
    )

}

To format the this.state.ImageData it took us a bit of fiddling to get the formatting/schema right for the SectionList. The format itself is documented at RN documentation. Hope that this helps!

Upvotes: 0

Related Questions