Search code examples
react-nativereact-native-router-flux

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 !


Solution

  • 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!