Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

107
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda