How to ensure my useState is saving the correct number of items and display it out at the same time

I have the following code:

let allurl = []
const [toReadurl, setToReadurl] = useState([])
useEffect(() => {

  
  const listRef = sRef(storage, paramKey)

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

    console.log(toReadurl)

This piece of code above is to get the download url from the items that are stored in firebase storage. The above works and I am able to read 4 different URL out but when I tried to store it in toReadurl, it only get to store 2 url instead of 4 url. How do I ensure toReadurl gets to store all 4 properly.

Another issue is where I tried to display it out

<Text>{toReadurl}</Text>

It display the first url only

I tried

<Text>{toReadurl[0]}</Text>
<Text>{toReadurl[1]}</Text>

It display only the last item in the array for both. What do I do to display it out properly?

Hi @calvinthecat

If you’re asking questions about useState() and how to use it and related things, that is part of React. This is not an Expo question or a React Native question.

But I had a quick look at your code and it seems that you are modifying the array that you store in toReadUrl. This is a no-no because React decides whether or not to update the state based on object identity. Since it is still the same object, it doesn’t get updated when you call setToReadurl().

Instead of this:

let allurl = [];
# [...]
          allurl.push(url);
          setToReadurl(allurl);

you should be able to do this:

          setToReadurl((urls) => [...urls, url]);

See also:
set functions, like setSomething(nextState)

The set function returned by useState lets you update the state to a different value and trigger a re-render. You can pass the next state directly, or a function that calculates it from the previous state:

You are trying to add something to the array of URLs. So you’re “calculating the new state from the previous state”. So instead of giving it the list directly you can give it a function that updates the list. The function in this case is:

(urls) => [...urls, url]