How to loop though folders (and subfolders with images) in React Native?

Viewed 936

I'm trying to list down sets of images. I have multiple folders in ./assets

./assets
├── 1x3
│   ├── 1.jpg
│   ├── 2.jpg
│   └── 3.jpg 
└── 3x3
    ├── 1.jpg
    ├── 2.jpg
    ├── 3.jpg
    ├── 4.jpg
    ├── 5.jpg
    ├── 6.jpg
    ├── 7.jpg
    ├── 8.jpg
    └── 9.jpg

I'd prefer to loop through ./assets for subfolders, and loop through each subfolder for images. I have tried looking online for solutions but they don't seem to work.

I have tried:

import React, { FC, ReactElement, useEffect, useState } from "react";
import { StyleSheet, View } from "react-native";

interface GalleryProps {
    handle: string;
}

const importAll = (r) => {
    return r.keys().map(r);
}

const Gallery: FC<GalleryProps> = (props: GalleryProps): ReactElement => {
    const [listOfImages, setListOfImages] = useState<any>([])
    useEffect(() => {
        setListOfImages(importAll(require.context('../assets/1x3', false, /\.(png|jpe?g|svg)$/)));
    }, [])

    return (
        <View style={styles.wrapper}>
            <View>
                {
                    listOfImages.map(
                        (image, index) => <img key={index} src={image} ></img>
                    )
                }
            </View>
        </View>
    );
};

const styles = StyleSheet.create({
    wrapper: {
        flex: 1,
        backgroundColor: "lavenderblush",
        alignItems: "center",
        justifyContent: "center",
    },
});

export default Gallery;

But I get this error: _$$_REQUIRE.context is not a function. (In '_$$_REQUIRE.context('../assets/1x3', false, /\.(png|jpe?g|svg)$/','_$$_REQUIRE.context' is undefined

Ideally, I hope to achieve something like (pseudocode):

const Parent() {
    return (
        for (subfolders in folder) { // or folders.map(subfolder => ...)
            return <Child props={subfolder}>
        }
    )
}

and

const Child(props) {
    return (
        for (images in props.subfolder) { // or props.subfolder.map(image => ...)
            return <img src="image" />
        )
    )
}

I have also tried react-native-fs (but apparently this is for the device's folder). Any help is appreciated.

2 Answers

The react-native bundler packages all resources like images at build-time. As a result it is not possible to loop over a folder and include all resources. This is mentioned in the documentation of the Image component.

https://reactnative.dev/docs/images

In order for this to work, the image name in require has to be known statically.

As a result, you will need to explicitly include all images.

Edit: The following is a solution to React.js and NOT React Native.

I know this is a bit late, but I came up with a workaround.

Start by creating a Python file outside of your React app folders. You can then use the following to obtain a list of your file names inside the folder of interest:

**Python**
import os.path
import os

files = []
directory = "C:/path/to/folder"
for filename in os.listdir(directory):
    f = os.path.join(directory, filename)
    if os.path.isfile(f):
        f = f.split("\\")
        file_name = f[1]
        files.append(file_name)

After saving the file names to the list, you can then write it to a JSON file inside of the src folder of your React app. Example:

**Python**
import os.path
import json

path = "C:/path/to/src"
name = "fileNamesList.json"
json_file_name = os.path.join(path, name)
with open(json_file_name, "w") as outfile:
        json.dump(files, outfile, ensure_ascii=False)

Now that you have a saved JSON file in your src folder, you can use React to retrieve the names inside of it! Just use a for loop:

**React.js**
const data = require('C:/path/to/src/fileNamesList.json');
for (let i=0; i<data.length; i++){
    // do something
}

Personally, I took each name from the JSON file and parsed it. Next, I used a for loop to get the info inside of each file.

Hope this helps!

Related