3

I'm super new to the world of Javascript and React. I'm currently building an app using the Ionic framework. It's using an existing firebase Project.

Im trying to fetch avatar images from firebase storage, using this function in my react component:

  async function getAvatarRef(avatarId: string): Promise<String> {
    const avatarUrl = await avatarsRef.child(avatarId).getDownloadURL();
    return avatarUrl.toString();
  }

then I'm calling that function to get the download URL using the UserID that I'm grabbing from Firebase Auth here:

<IonImg src={getAvatarRef(child.avatarId)} />

My issue though is that the function is returning a Promise<string> but the src property from IonImage is wanting just a simple String type

This is the error I'm getting: Type 'Promise<string>' is not assignable to type 'string'.

I've looked all over but can't seem to find a solution.

Anyone here have any ideas?

  • 4
    All async functions always return a promise that resolves asynchronously. You won't be able to make it synchronous - the final promise must be awaited or dealt with somehow. – Doug Stevenson Aug 11 '20 at 02:30
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Emile Bergeron Aug 11 '20 at 03:24

3 Answers3

2

What you are doing is an effect. You are fetching data from a server and rendering that in your component.

If you are using functional components, you want to have a look at the useState and useEffect hooks. For class components, you need to use state and a lifecycle method on your component.

Essentially, your src attribute should be a state item (something that can change during the lifetime of your component that will require react to update the DOM) that you may initialize as an empty string or a local placeholder image.

Then your effect code would update the value of your state and react will handle telling the DOM what changed.

EDIT: I should add that there is nothing wrong with using an async function inside a useEffect hook. Note that the callback function useEffect expects cannot be asynchronous. But there is nothing stopping you from putting an async function inside the callback and calling it there. Or using an async IIFE. Both are common patterns in React...

Abraham Labkovsky
  • 1,771
  • 6
  • 12
1

React hooks would be applicable in situations like this. Here's an example using your code snippets

function YourComp() {
      const [avatarUrl, setAvatarUrl] = useState<string>('');

      // run effect once 
     useEffect(() => {
        getUrl();
      }, []);
         
      async function getAvatarRef(avatarId: string): Promise<String> {
        const avatarUrl = await avatarsRef.child(avatarId).getDownloadURL();
        return avatarUrl.toString();
      }

     // Resolve Promise<string> to string
      const getUrl = (): void => getAvatarRef(
       child.avatarId
      ).then((res) =>
        setAvatarUrl(res.avatarUrl)
      );


     
      return <IonImg src={avatarUrl} />
    }
laujonat
  • 342
  • 1
  • 8
-1

Instead call the promise first then set the src using the result

getAvatarRef(child.avatarId).then(src=> someImg.src=src)