Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

106
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda