无法通过 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(...)
结果
一般来说,不要混合使用
await
和
then
,请使用其中一种
此外,如果 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