开发者问题收集

无法通过 API 渲染图像

2022-05-16
710

我能够从 API 端点获取数据,但无法将其呈现到屏幕上。

这是我的 App.js 组件。

    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>
  );
}

这是我的卡片组件。

    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>

我发现返回的是承诺而不是获取的数据。如果我取消注释 setImg 承诺,则会连续获取图像但仍无法呈现。请帮忙。提前致谢。

3个回答

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>
  );
}

卡片组件:

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>
VMT
2022-05-16

您没有使用 await fetch(...) 结果

一般来说,不要混合使用 awaitthen ,请使用其中一种

此外,如果 api 返回图像数据,您不应将其转换为文本,而应转换为 blob,并使用 URL.createObjectURL 创建正确的 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)

或者如果可以,直接使用 api url:

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

但您应该使用状态来存储生成的 URL。此代码可用于您的 fetchData() 函数,并将 imageUrl 添加到每个项目,以便在每次渲染时不重新获取

Maneal
2022-05-16

问题

问题是,在渲染 data 数组时,会无条件调用 fetchData 函数。当取消注释 .then((text)=>setImg(text)) 时,它会更新状态并触发重新渲染。重复进行,直到令人厌烦。

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)) // <-- (2) update state, trigger rerender
      .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)} // <-- (1) immediately invoked!
            phone={details.phone}
            website={details.website}
            company={details.company.name}
          />
        );
      })}
    </div>
  );
}

解决方案

您似乎不需要“获取”图像,只需使用计算出的图像源值即可。如果需要,请创建一个实用函数。

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

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

  // (1) utility function to compute image source string
  const getImageSrc = name => {
    return `https://avatars.dicebear.com/v2/avataaars/${name}.svg?options[mood][]=angry`
  };

  return (
    <div className="App">
      {data.map((details) => {
        return (
          <Card
            key={details.id}
            email={details.email}
            name={details.name}
            image={getImageSrc(details.name)} // <-- (2) call utility
            phone={details.phone}
            website={details.website}
            company={details.company.name}
          />
        );
      })}
    </div>
  );
}
Drew Reese
2022-05-16