我在 Next 应用程序中遇到图像加载问题。当某些图像(尤其是高尺寸图像)似乎未完全上传时,就会出现问题。因此,我正在寻求有关如何有效处理此问题的建议。
相关代码是名为 TextToImagestyles 的 React 功能组件的一部分。在此组件中,图像是动态加载的,并且在获取图像时会显示加载骨架。但是,由于某些图像尺寸较大,加载可能无法按预期完成。
const TextToImagestyles: React.FC<TextToImageStylesInterface> = (props) => {
const [imageLoaded, setImageLoaded] = useState(false);
useEffect(() => {
const image = new window.Image();
image.src = props.icon;
if (image.complete) {
setImageLoaded(true);
} else {
image.onload = () => {
setImageLoaded(true);
};
}
}, [props.icon]);
return (
<>
{!props.icon ? (
<Skeleton
startColor="#3D3E41"
endColor="#2B2C2F"
w={props.width}
h={props.height}
/>
) : (
<GridItem
w={props.width}
key={props.uniqueKey}
onClick={() =>
props.handleStyleClick(
props.uniqueKey,
props.title,
props.stylesName
)
}
>
<Box pos={"relative"}>
{imageLoaded ? (
<Image
src={props.icon}
w={props.width}
h={props.height}
border={
props.selectedStyleImageIndex === props.uniqueKey
? "1px solid #19F4D4"
: "1px solid rgba(25, 19, 36, 1)"
}
borderRadius={"10px"}
cursor={"pointer"}
alt="model"
/>
) : (
<Skeleton
startColor="#3D3E41"
endColor="#2B2C2F"
w={props.width}
h={props.height}
/>
)}
<Box
pos={"absolute"}
top={0}
left={0}
w={props.width}
h={props.height}
bgGradient={
"linear(to top, rgba(25, 19, 36, 1), rgba(25, 19, 36, 0))"
}
borderRadius={"10px"}
></Box>
<Flex justify={"center"} w={"100%"}>
<Text
pos={"absolute"}
color={"#ffffff"}
bottom={"3px"}
w={"90%"}
textAlign={"center"}
fontFamily="Poppins"
fontSize={"10px"}
maxWidth="100%"
fontWeight={500}
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
}}
title={props.title}
>
{props.title}
</Text>
</Flex>
</Box>
</GridItem>
)}
</>
);
};
设置图像加载超时,如果在该时间内未加载,则显示后备 UI 或重试加载图像。
const TextToImagestyles: React.FC<TextToImageStylesInterface> = (props) => {
const [imageLoaded, setImageLoaded] = useState(false);
const [loadTimeoutExceeded, setLoadTimeoutExceeded] = useState(false);
const [retryCount, setRetryCount] = useState(0);
useEffect(() => {
const image = new window.Image();
image.src = props.icon;
let timeoutId;
const loadImage = () => {
if (image.complete) {
setImageLoaded(true);
} else {
image.onload = () => {
setImageLoaded(true);
clearTimeout(timeoutId);
};
// Set a fallback timeout (e.g., 5 seconds)
timeoutId = setTimeout(() => {
setLoadTimeoutExceeded(true);
}, 5000);
}
};
loadImage();
return () => clearTimeout(timeoutId); // Cleanup timeout on unmount
}, [props.icon, retryCount]);
const handleRetry = () => {
setLoadTimeoutExceeded(false);
setImageLoaded(false);
setRetryCount(retryCount + 1);
};
return (
<>
{!props.icon ? (
// Your existing Skeleton component for when icon is not provided
) : (
<>
{loadTimeoutExceeded ? (
// Fallback UI when timeout is exceeded
<div>
<p>Failed to load the image. Click to retry.</p>
<button onClick={handleRetry}>Retry</button>
</div>
) : (
// Your existing GridItem component
)}
</>
)}
</>
);
};