When trying to pull the array, the data is always empty. Does anyone know where I'm going wrong? I checked the console and as far as I can tell, there is a reference to the firebase storage but no data. But there are 4 documents in my storage that should output URL links. This is my component
import React, { useState, useEffect } from 'react'; // i'm initializing firebase with firebase.initializeApp(firebaseConfig) import { projectStorage } from '@/firebaseConfig'; // projectStorage is = firebase.storage(); const PDFViewer = () => { const [pdfUrls, setPdfUrls] = useState(); useEffect(()=>{ const storageRef = projectStorage.ref(); const pdfRef = storageRef.child('myfirebaselocationpath/uploadeddocs/'); const urls = []; pdfRef.listAll().then((result) => { result.items.forEach((itemRef) => { itemRef.getDownloadURL().then((url) => { urls.push(url); }); }); setPdfUrls(urls); }).catch((error) => { console.error('Error retrieving PDF files:', error); }); },[]) console.log(pdfUrls) /* console.log( pdfUrls.map((url) => { return url }) ) */ return ( <div> <h1>PDF Viewer</h1> {pdfUrls.map((url) => ( <iframe key={url} src={url} width="100%" height="600px" /> ))} </div> ); }; export default PDFViewer;`
The component above is what I tried and expected a linked list to be mapped, but no data was displayed. And pdfUrls is always empty.
The problem lies here:
listAll
andgetDownloadURL
are asynchronous operations and may take some time to complete. The main code does not block the entire script, but continues execution while the operation occurs - and then executes the callback block when the data (file list or download URL) is available.This means that your
setPdfUrls(urls);
runs before anyurls.push(url);
runs, and this sets an empty list. I recommend checking this in a debugger, or adding some logging.The easiest way to solve the problem is to move
setPdfUrls(urls);
to the internal callback:Now it will be called after each download URL is determined. This will perform multiple updates, so it may cause some flickering in the UI, but the data should now appear.
Calling just once while waiting for everything to complete
setPdfUrls(urls);
requires more work. The easiest way is probably to mark the entireuseEffect
handler asasync
and useawait
in it:So this code:
await
to ensure that the asynchronous operation completes before callingsetPdfUrls
.for...of
loop to ensure we can useawait
within the loop.