Search code examples
javascriptreactjsreact-nativefetch

How can flexbox be used to layout Views in two rows and and unknown amount of columns in React Native?


I am receiving an unknown amount of data(images) from an API endpoint and I want to use flexbox to display the images in 2 rows and an unknown amount of columns depending on the amount of data. How is it done?

const [artistes, setArtiste] = useState(null);
        //get request to endpoint
        fetch('http://localhost:8000/museb/artist/',{
            method: 'GET',
            headers: {
              Accept: 'application/json',
              'Content-Type': 'application/json',
            }})
        .then(response => response.json())
        .then(jsonResponse => 
            setArtiste(jsonResponse)
        )
        .catch(error => console.log(error))
        .finally(setLoading(false));


        
    }, [])

This is where I'm rendering the data

                    <View style={{flexDirection: "row"}}>
                        {artistes.map((artiste, index) => (
                    <TouchableOpacity key={index} onPress={() => navigation.navigate("Musicplayer")} style={styles.musiccontentsmall}>
                    <Image source={{uri: "http://localhost:8000"+artiste.image}} style={styles.smallimage}/>
                    </TouchableOpacity>))}
                    </View>
                    )}

"flexDireciton: row" will put all the content in a single row, but I want it to be in two rows


Solution

  • Here you have two options.

    The first one is answering your specific question using flexbox only: The trick here is using the wrap style, combining the width size, so with 50% we use two columns or 33% we use three.

    <View style={{flexDirection: "row", flexWrap: "wrap"}}>
      {artistes.map((artiste, index) => (
        <TouchableOpacity key={index} onPress={() => navigation.navigate("Musicplayer")} style={[styles.musiccontentsma, { width:"50%" }]}>
        <Image source={{uri: "http://localhost:8000"+artiste.image}} style={styles.smallimag}/>
        </TouchableOpacity>
        ))}
    </View>
    

    The second option and the best one in terms of performance (because you are using images):

    <FlatList
      data={artistes}
      numColumns={2}
      renderItem={({ item }) => this._renderItem(item)}
      keyExtractor={(item, index) => index.toString()}
    />
    
    _renderItem = item => {
      return (
        <View styles={{ flex: 0.5 }}>
          {...}
        </View>
      )
    }