How to pass an array to Firestore?

I’m trying to pass an array to Firestore using the code below. The problem is the array is always empty in Firestore. If I pass an array manually, it works. If I console.log the array it outputs, it’s not empty.

const handleSubmit = (e) => {
    ...
    finally {
        ...
        console.log(photoUrlArray) // THIS OUTPUTS THE ARRAY

        collectionRef.add({
            field1: someData,  THIS GETS POSTED
            photos: photoUrlArray,    THIS DOESN'T
        })
    }
}

If manually post an array, it works.

collectionRef.add({
    field1: someData,  
    photos: ["url1,jpg","url2.png", "url3.wepb"]  THIS WORKS
})

I realise I’ve very probably missed something completely obvious. Can anyone see what the error is, please?

The output of console.log(photoArray) is:

[]
0: "https://firebasestorage.googleapis.com/v0/i/t2-dev-9.appspot.com/o/photo2.jpeg?alt=media&token=82e3bd7d-a77a-4045-af71-1a7851bddd7c"
1: "https://firebasestorage.googleapis.com/v0/i/t2-dev-9.appspot.com/o/photo.jpeg?alt=media&token=c71f2fbe-ca64-4189-9403-4d24f1433d77"

length: 2

EDIT: HERE’S THE BASIC VERSION OF THE ENTIRE COMPONENT. The component takes a multiple selection of images from the input, cycles through them and uploads them to Firebase Storage, and pushes the storage URL to the ‘photoArray’ array’. How do I post photoArray or the contents thereof, to Firestore?

export default function AddPost() {
    
    const fileInput = useRef();
    const photoArray = [];

    function handleSubmit(e) {
        e.preventDefault()
        
        let fileArray = fileInput.current.files;
        for (let i = 0; i < fileArray.length; i++) {
            handleUpload(fileArray[i]);
        }

        console.log(photoArray); // OUTPUTS THE ARRAY
        const collectionRef = useFireStore.collection('posts');
        collectionRef.add({
            field1: someData,   // WORKS
            field2: someMoreData,    // WORKS
            photos: photoArray,    // DOESN'T
        })
    }

    function handleUpload() {
        
        const storageRef = useStorage.ref()
        const fileRef = storageRef.child(file.name)

        fileRef.put(file).then(() => {
            fileRef.getDownloadURL().then(function (url) {
                photoArray.push(url)
            });
       })

    }

    return (
        <form onSubmit={handleSubmit}>
            <input type="file" ref={fileInput}/>
        </form>
    )

}

Cheers, Matt

Answer

Here’s some (untested) code.

Look how handleUpload now returns a promise, so that you can wait for it to finish before continuing.

export default function AddPost() {

    const fileInput = useRef();
    const photoArray = [];

    function handleSubmit(e) {
        e.preventDefault();

        let fileArray = fileInput.current.files;
        const uploadTasks = [];
        for (let i = 0; i < fileArray.length; i++) {
            uploadTasks.push(handleUpload(fileArray[i]));
        }
        Promise.all(uploadTasks).then(() => {
            console.log(photoArray); // OUTPUTS THE ARRAY
            const collectionRef = useFireStore.collection('posts');
            collectionRef.add({
                field1: someData,   // WORKS
                field2: someMoreData,    // WORKS
                photos: photoArray,    // SHOULD WORK NOW!
            });
        });
    }

    function handleUpload() {

        const storageRef = useStorage.ref();
        const fileRef = storageRef.child(file.name);

        return fileRef.put(file).then(() => {
            return fileRef.getDownloadURL().then(function (url) {
                photoArray.push(url);
            });
        });

    }

    return (
        <form onSubmit={handleSubmit}>
            <input type="file" ref={fileInput} />
        </form>
    );

}

The order of the photos will most likely be wrong, since they’re all uploaded in parallel and their URLs are added when their respective uploads are completed. I’m leaving you to find a way to fix it if you need to.

I also recommend that you use async / await instead of then() whenever possible.

Leave a Reply

Your email address will not be published. Required fields are marked *