0

I'm trying to load data using React and Firebase. Unfortunately, I can't get it to display them. In Firebase's res.items.forEach((itemRef) function, I fill an array. I would like to access this later. However, this is then empty. How so ?

const array = [];


function loadList() {
const storage = getStorage();

const storageRef = sRef(storage, "images/");

// Find all the prefixes and items.
listAll(storageRef)
.then((res) => {
  res.prefixes.forEach((folderRef) => {
    // All the prefixes under listRef.
    // You may call listAll() recursively on them.
  });
  res.items.forEach((itemRef) => {
    array.push(itemRef._location);
    // All the items under listRef.
    console.log(itemRef._location);
  });
})
.catch((error) => {
  // Uh-oh, an error occurred!
  });
}

function App() {


loadList();

return (
<div className="App">
  <Stack direction="row" alignItems="center" spacing={2}>
    // ARRAY IS EMPTY
    {array?.map((value, key) => {
      return <h1>{value}</h1>;
    })}


  ...

1 Answer 1

1

From your explaination, here is what I gathered you are trying to do:

  1. Fetch the documents from cloud firestore.
  2. Store them in an array.
  3. 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>

    )
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.