由于useState,图像在React中加载的时间是原来的两倍



我有以下渲染图像的逻辑,当前流如下:如果状态为false,则显示微调器,然后当图像加载时,微调器消失。

这里的核心问题是,状态是重新渲染导致图像再次加载的组件。关于如何在图像加载后进行即时切换,我有点没有选择了。

它不是循环,而是图像再次重新加载,即使由于setLoading(true)引起的渲染而已经加载了图像。

如何防止重新加载。useEffect逻辑只是加载图像的模拟器,但我的真实图像来自icons变量。

export const iconsImg: React.FC<Props> = ({ img: string }) => {
useEffect(() => {
let newImg = new Image();
newImg.src = icons[img].props.src;
newImg.onload = () => {
setLoading(true);
};
}, []);

const icons: iconsInterface = {
a: <img className={classes.imgStyle} alt="a" src={link} />,
b: <img className={classes.imgStyle} alt="b" src={link} />,
}
const [loading, setLoading] = useState(false);
return ( 
<React.Fragment>
{!loading ? (
<Spinner>
) : (
icons[img]
)}
</React.Fragment>
)}

问题

上一次尝试的问题是,您从显示Spinnerloading开始,并且您试图在加载映像后切换状态,但这种情况永远不会发生,因为映像没有安装在DOM中。

创建icons并不等同于创建img,直到它被添加到return中并安装到DOM中。我认为它加载了两次,因为在某个时刻,您直接或在loading更改后将其中两个添加到DOM中。

解决方案

您可以简化您的组件,如下所示。注意,我在创建图像时删除了icons并设置了alt属性(两者之间的一个区别(。那个setTimeout就是我们看到的加载器。您可以稍后将其删除。

const IconsImg  = ({ img }) => {
const [loading, setLoding] = React.useState(true);
return <div >{loading && "Loading..."} <img alt={img} style={{display: loading ? "none" : "block"}} onLoad= {()=> setTimeout(()=> setLoding(false), 1000)} src = "https://images.unsplash.com/photo-1657664042206-1a98fa4d153d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDF8MHxlZGl0b3JpYWwtZmVlZHwxfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=500&q=60"/></div>;
};
/* The below code is to have a working example here at Stack Overflow */
ReactDOM.render(
<IconsImg img= "car" />,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

newImgicons[img]是不同的对象。loading设置时对于true,浏览器这次为icons[img]加载相同的src。

你可以试试这个:

如果loadingfalse,则首先为icons[img]设置display:none

和:

<React.Fragment>
{loading || (
<Spinner>
)}
icons[img]
</React.Fragment>

然后:

useEffect(() => {
icons[img].onload = () => {
setLoading(true);
};
}, []);

或更好:

<img className={classes.imgStyle} alt="a" src={link} onload={() => setLoading(true)}/>

最新更新