Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

108
Views
How return url for a img tag with a function

so I'm rendering out an array of posts. Each post has a unique user id associated with it, which I'm trying to use in another API call to return the user's image for that post.

Currently i have it setup like so

Rendering out the post

             {data?.map((data) => (
                <div className="allpostsingle" key={data.id} onClick={() => sendTo(data.id)}>
                    <div className="allpostheader">
                        <img src={getUrl(data.user)}/>
                        <p>{data?.description}</p>
                    </div>
                </div>
              ))}

The function to get the image URL

   const getUrl = async (id) => {
       let url = `http://127.0.0.1:8000/api/user/${id}/`
       const response = await fetch(url)
       const data = await response.json()
       const avatarurl = data.avatar
       return avatarurl
   }

The issue with this is it returns a promise instead of the URL. I know you can set it in a state to get the url, but then it wouldnt be unique to each post?

Im just wondering how i can solve this or if theres a different way to solve this issue.

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

It doesn't work because rendering in react in synchronous while your getUrl is an async function. As some other answers pointed out, you can fetch all url in componentDidMount or useEffect hook and update the state.

If you don't want to change your existing code, you can also replace img with a react component of your own so it can handle promise.

function Image({src}){
  const [actualSrc, setActualSrc] = useState('placeholder image link')
  useEffect(()=>{
    src.then((url) => setActualSrc(url));
  }, [src]);
  
  return <img src={actualSrc}/>
}
{data?.map((data) => (
  <div className="allpostsingle" key={data.id} onClick={() => sendTo(data.id)}>
    <div className="allpostheader">
      <Image src={getUrl(data.user)}/>
      <p>{data?.description}</p>
    </div>
  </div>
))}
const getUrl = async (id) => {
       let url = `http://127.0.0.1:8000/api/user/${id}/`
       const response = await fetch(url)
       const data = await response.json()
       const avatarurl = data.avatar
       return avatarurl
}

This may not be best for performance as getUrl will send a new reference of promise on each render. In this case, best would be to pass id (user id in getUrl) to the Image component instead of a promise and have logic of fetching the actualUrl inside of it.

function Image({userId}){
  const [actualSrc, setActualSrc] = useState('placeholder image link')
  useEffect(()=>{
    const getUrl = async (id) => {
       let url = `http://127.0.0.1:8000/api/user/${id}/`
       const response = await fetch(url)
       const data = await response.json()
       const avatarurl = data.avatar
       return avatarurl;

    getUrl(userId).then((url) => setActualSrc(url));
  }, [userId]);
  
  return <img src={actualSrc}/>
}
{data?.map((data) => (
  <div className="allpostsingle" key={data.id} onClick={() => sendTo(data.id)}>
    <div className="allpostheader">
      <Image userId={data.user} />
      <p>{data?.description}</p>
    </div>
  </div>
))}
about 4 years ago · Juan Pablo Isaza Report

0

You can't assign the return value of getUrl() to the src attribute because it is asynchronous and returns a Promise.

What you can do instead is maintain another piece of state for the user avatars that updates when your data does. For example, create a function that resolves user avatars

const resolveUserAvatars = async (users) => {
  const avatars = await Promise.allSettled(users.map(async ({ user }) => {
    const res = await fetch(`http://127.0.0.1:8000/api/user/${encodeURIComponent(user)}/`)
    if (!res.ok) {
      throw new Error(res.status)
    }

    return {
      user,
      avatar: (await res.json()).avatar
    }
  }))

  return Object.fromEntries(
    avatars
      .filter(({ status }) => status === "fulfilled")
      .map(({ value: { user, avatar } }) => [ user, avatar ])
    )
  )
}

Then in your component...

const [ data, setData ] = useState([]) // init as an array
const [ avatars, setAvatars ] = useState({})
// avatars will look like
// { userId: imageUrl, ... }

useEffect(() => {
  resolveUserAvatars.then(setAvatars)
}, [ data ]) // execute when data changes

and in your JSX

{data.map(({ id, user, description }) => (
  <div className="allpostsingle" key={id} onClick={() => sendTo(id)}>
    <div className="allpostheader">
      <img src={avatars[user] ?? "some/placeholder.png"}/>
      <p>{description}</p>
    </div>
 </div>
))}

See also Promise.allSettled()

about 4 years ago · Juan Pablo Isaza Report

0

It's not a good idea to get each user's avatar separately and send request for each post and every time render post items, If it's possible for you and the backend api just include users avatar url in post so easily render it. if its not possible and have a limitation in api you just need to get all post user data with Promiss.allSettled in useEffect after the post data has recieved and attach user data to postItem or keep it in separate dictionary then set the state to render the post and user avatar url in it.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!