From your explaination, here is what I gathered you are trying to do:
- Fetch the documents from cloud firestore.
- Store them in an array.
- Create a list of Components in the browser view rendered by react using the array that was fetched.
For such, fetching and rendering tasks, your best bet would be using Callbacks, State and Effect.
So:
- State would hold the values for react to render.
- Effect will fetch the data when the component loads.
- Callback will do the actual fetching because asynchronous fetching on useEffect directly is discouraged.
const storage = getStorage();
const listRef = ref(storage, 'files/uid');
function ImageApp()
{
// This is the array state of items that react will eventually render
// It is set to empty initially because we will have to fetch the data
const [items, setItems] = React.useState([]);
React.useEffect(() =>
{
fetchItemsFromFirebase();
}, []); // <- Empty array means this will only run when ImageApp is intially rendered, similar to onComponentMount for class
const fetchItemsFromFirebase = React.useCallback(async () =>
{
await listAll(listRef)
.then((res) =>
{
// If (res.items) is already an array, then use the method below, it would be faster than iterating over every single location
// cosnt values = res.items.map((item) => item._location);
// If res.items doesnt already return an array, then you unfortunately have to add each item individually
const values = [];
for (const itemRef of res.items)
{
values.push(itemRef._location);
}
console.log(values);
setItems(values);
})
.catch((error) => { console.error(error) });
}, []); // <- add "useState" values inside the array if you want the fetch to happen every smth it changes
return (
<div className="App">
{
items && // Makes sure the fragment below will only be rendered if `items` is not undefined
// An empty array is not undefined so this will always return false, but its good to use for the future :)
<>
{
(items.map((item, itemIndex) =>
<h1 key={ itemIndex }>{ item }</h1>
))
}
</>
}
</div>
)
}