如何避免react-intersection-observer下图片重复加载?
解决建议
方案1:用状态记录加载状态,保留src仅控制显示隐藏
核心思路是仅在元素首次进入视口时加载图片,之后固定src地址,通过CSS控制图片的显示/隐藏,避免因src重置触发重复请求。
修改后的代码如下:
import * as React from "react"; import { createRoot } from "react-dom/client"; import { useInView } from "react-intersection-observer"; import "./styles.css"; function App() { const { ref, inView } = useInView({ threshold: 0 }); // 记录图片是否已完成首次加载 const [isImageLoaded, setIsImageLoaded] = React.useState(false); // 元素首次进入视口时,标记图片为已加载 React.useEffect(() => { if (inView && !isImageLoaded) { setIsImageLoaded(true); } }, [inView, isImageLoaded]); return ( <> <div style={{ height: "200vh" }}>eeeeee</div> <div ref={ref} className="inview-block"> <h2> <img // 加载完成后永久保留真实地址 src={isImageLoaded ? "https://inviewimaging.com/wp-content/uploads/2015/04/Inview-Graphic.png" : null} alt="" // 根据是否在视口控制显示状态 style={{ display: inView ? "block" : "none" }} /> </h2> </div> </> ); } const root = createRoot(document.getElementById("root")); root.render(<App />);
方案2:结合原生懒加载,用inView控制显示
如果允许图片DOM提前存在,可直接设置src并开启原生懒加载,通过inView控制显示状态,利用浏览器缓存避免重复请求:
import * as React from "react"; import { createRoot } from "react-dom/client"; import { useInView } from "react-intersection-observer"; import "./styles.css"; function App() { const { ref, inView } = useInView({ threshold: 0 }); const IMAGE_URL = "https://inviewimaging.com/wp-content/uploads/2015/04/Inview-Graphic.png"; return ( <> <div style={{ height: "200vh" }}>eeeeee</div> <div ref={ref} className="inview-block"> <h2> <img src={IMAGE_URL} alt="" // 初始隐藏,进入视口后显示,移出则隐藏 style={{ display: inView ? "block" : "none" }} // 开启原生懒加载,仅当元素接近视口时才加载 loading="lazy" /> </h2> </div> </> ); } const root = createRoot(document.getElementById("root")); root.render(<App />);
方案说明
- 方案1适合需要严格控制初始请求量的场景,仅在元素首次进入视口才加载图片,后续仅切换显示状态。
- 方案2利用浏览器原生能力实现懒加载,代码更简洁,图片加载后会被浏览器缓存,再次进入视口不会重复发起请求。
内容的提问来源于stack exchange,提问作者user19883277
相关产品推荐
相关产品推荐

