想象一下我想创建一个组件来渲染图像。如果图像资源有效,则应通过css background-image
将其渲染为div。否则,我应该将其渲染为带有alt标签的标准<img>
。
所以我们得到这样的东西:
const ImageComponent = ({src}) => {
const [loaded, setLoaded] = useState(false);
const [renderFallback, setRenderFallback] = useState();
useEffect(() => {
const image = new Image();
image.onsuccess = () => {
setLoaded(true);
setRenderFallback(false);
}
image.onerror = () => {
setLoaded(true);
setRenderFallback(true);
}
image.src = src;
return () => {
// clean up listeners
image.onsuccess = undefined;
image.onerror = undefined;
}
}, [src]);
if (!loaded) { return null; }
return renderFallback ?
<div style={{backgroundImage: `url(${src})`}}/> :
<img src={src} alt="my alt"/>;
}
在这里,我们首先通过简单的javascript(在useEffect中)开始对图像进行抓取。如果有效,资源(由浏览器)将被缓存,并且随后的<div>
的呈现是瞬时的。
但是,如果资源无效,则没有适当的缓存机制(有关更多详细信息,请参见this question)。因此,当我们在Component的末尾呈现新的<img>
元素时,它会启动一个全新的请求以获取该图像(尽管推断该图像已损坏)。
因此,为了避免重复获取,一种可能的解决方案是呈现已经初始化的image
元素,而不是呈现该图像的新的react元素。
这可能吗?
评论反馈
https://goodreads.com
)background-image
CSS完成,因此我需要依赖标准的<img>
元素。因为我已经确定图像已损坏(在useEffect中),所以我想在React中渲染损坏的<img>
时避免新的获取。希望可以澄清一切!
答案 0 :(得分:1)
有效的定义是:图像已加载,并且宽度和高度都大于零。
现在有两种方法可以检查图像是否有效:
img
标签,然后检查图像是否有效。以下代码将首先假定图像无效。
import React, { useEffect, useRef, useState } from "react";
const ImageComponent = ({src}) => {
const container = useRef(null);
const [valid, setValid] = useState(false);
useEffect(() => {
container.current.innerHTML = '';
const image = new Image();
const checkValid = () => {
if (image.complete && image.naturalWidth > 0 && image.naturalHeight > 0) {
setValid(true);
container.current.appendChild(image);
}
}
image.onload = checkValid;
image.src = src;
}, [src]);
return (
<div>
<div ref={container} />
{!valid && <div>Image not valid</div>}
</div>
);
};
用法:
<ImageComponent src="IMAGE_URL" />
以下代码将首先假定图像有效。
import React, { useRef, useState } from 'react';
const ImageComponent = ({src}) => {
const image = useRef(null);
const [valid, setValid] = useState(true);
const checkValid = () => {
if (!image.current.complete || image.current.naturalWidth < 1 || image.current.naturalHeight < 1) setValid(false);
}
if (valid) {
return (
<img
src={src}
onLoad={checkValid}
onError={() => setValid(false)}
ref={image}
/>
);
}
return <div>Image not valid</div>;
};
用法:
<ImageComponent src="IMAGE_URL" />