Home > Blockchain >  Not able to render image from API
Not able to render image from API

Time:05-17

I am able to fetch the data from API endpoint but am not able to render it to the screen.

This is my App.js component.

    function App() {
  const [data, setData] = useState([]);
      const [img, setImg] = useState([]);

    

  useEffect(() => {
    fetchData(setData);
  }, []);

  async function fetchImage(name) {
    const requestOptions = {
      method: "GET",
      redirect: "follow",
    };
   await fetch(
      `https://avatars.dicebear.com/v2/avataaars/${name}.svg?options[mood][]=angry`,
      requestOptions
    )
      .then((response) => response.text())
      // .then((text)=>setImg(text))
      .catch((error) => console.log("error", error));
  }
  return (
    <div className="App">

      {data.map((details) => {
        return (
          <Card
            key={details.id}
            email={details.email}
            name={details.name}
            image={fetchImage(details.username)}
            phone={details.phone}
            website={details.website}
            company={details.company.name}
          />
        );
      })}
    </div>
  );
}

This is my card component.

    export default function Card(props) {
  return (
    <Box
      w="70vw"
      h="250px"
      borderWidth="1px"
      borderColor={"black"}
      overflow="hidden"
      m="2vh auto"
      display={"flex"}
      flexDir="row"
      color="black"
    >
      <Box>
        <Image
          w="20vw"
          h="250px"
          src={props.image}
          bg="gray"
        />
      </Box>

      <Box display='flex' flexDirection={'column'} alignItems='flex-start' ml='2vw' fontSize={'lg'}>
          <Box fontSize={'3xl'} mb='2vw'>{props.name}</Box>
          <Box><strong>Email: </strong>{props.email}</Box>
          <Box><strong>Phone: </strong>{props.phone}</Box>
          <Box><strong>Company: </strong>{props.company}</Box>
          <Box><strong>Website: </strong>{props.website}</Box>
          <Box><strong>Address: </strong>{props.address}</Box>
      </Box>
    </Box>

I figured out is returning promise instead of fetched data. If I uncomment the setImg promise, images are fetched continuously but still not rendering. Please help. Thanks in advance.

CodePudding user response:

I hope below code help you.

App.js:

function App() {
  const [data, setData] = useState("");

  useEffect(() => {
    fetchData(setData);
  }, []);

  return (
    <div className="App">

      {data.map((details) => {
        return (
          <Card
            key={details.id}
            email={details.email}
            name={details.name}
            username={details.username} // <=== Change image prop to username prop
            phone={details.phone}
            website={details.website}
            company={details.company.name}
          />
        );
      })}
    </div>
  );
}

Card component:

export default function Card(props) {
  const imgURL = `https://avatars.dicebear.com/v2/avataaars/${props?.name}.svg?options[mood][]=angry`
  return (
    <Box
      w="70vw"
      h="250px"
      borderWidth="1px"
      borderColor={"black"}
      overflow="hidden"
      m="2vh auto"
      display={"flex"}
      flexDir="row"
      color="black"
    >
      <Box>
        <Image
          w="20vw"
          h="250px"
          src={imgURL} //<=== This is src img
          bg="gray"
        />
      </Box>

      <Box display='flex' flexDirection={'column'} alignItems='flex-start' ml='2vw' fontSize={'lg'}>
          <Box fontSize={'3xl'} mb='2vw'>{props.name}</Box>
          <Box><strong>Email: </strong>{props.email}</Box>
          <Box><strong>Phone: </strong>{props.phone}</Box>
          <Box><strong>Company: </strong>{props.company}</Box>
          <Box><strong>Website: </strong>{props.website}</Box>
          <Box><strong>Address: </strong>{props.address}</Box>
      </Box>
    </Box>

CodePudding user response:

You'r not using the await fetch(...) result

In general, don't mix await and then use one or another

Plus, if api returns image data, you should not convert it to text, but to blob and use URL.createObjectURL to create a correct url

const response = await fetch(
      `https://avatars.dicebear.com/v2/avataaars/${name}.svg?options[mood][]=angry`,
      requestOptions
    )
const blob = await response.blob();
return URL.createObjectURL(blob)

Or use the api url directly if you can:

return `https://avatars.dicebear.com/v2/avataaars/${name}.svg?options[mood][]=angry`;

But you should use state to store the generated URLs. This code could be used in your fetchData() function and add the imageUrl to each item to not refetch on each render

  • Related