React: 在更新前显示加载中的内容覆盖在先前的图像上。

huangapple go评论70阅读模式
英文:

React: show loading over prev image before it gets updated

问题

我有一个每隔1分钟重新加载的图像。每当1分钟完成时,会获取新的图像(我在img的src属性中使用嵌入的链接),就像<img src={link} />

问题是,当加载和获取新图像时,该图像组件会消失,稍后当获取新图像时,它才会显示该新图像。
我的需求是在加载新图像并替换旧图像之前,在以前的图像上显示"加载中..."。
简而言之,我不希望旧图像消失,新图像出现。我希望保留旧图像并在上面添加加载覆盖文本,并将该图像替换为新内容,然后隐藏"加载中..."文本。

const [isLoading, setIsLoading] = useState(true);

在返回部分:

<div className={styles.wrapper} style={{ opacity: isLoading ? "0.3" : "1" }}>
    <img src={src} onLoad={() => setIsLoading(false)} />
    <div>
      {isLoading && (
        <div className={styles.overlayLoading}>
          加载中...
        </div>
      )}
    </div>
  </div>
英文:

I have an image that is reloaded every 1 min. Every time 1 min is completed, the new image is fetched. (I use the embedded link inside the src attribute of img), like &lt;img src={link} /&gt;.

The problem is while a new image is loading and fetching, that image component is disappeared and later when the new image is fetched, it will show that new image.
My requirement is to show loading... over the previous image before the new image is loaded and replaces the old one.
In short, I don't want the old one to disappear and a new one appears. I want to keep an old one with loading overlay text and replace that image with a new content and hide loading... text.

  const [isLoading, setIsLoading] = useState(true);

inside return:

 &lt;div className={styles.wrapper} style={{ opacity: isLoading ? &quot;0.3&quot; : &quot;1&quot; }}&gt;
    &lt;img src={src} onLoad={() =&gt; setIsLoading(false)} /&gt;
    &lt;div&gt;
      {isLoading &amp;&amp; (
        &lt;div className={styles.overlayLoading}&gt;
          Loading...
        &lt;/div&gt;
      )}
    &lt;/div&gt;
  &lt;/div&gt;

答案1

得分: 2

以下是代码部分的翻译:

你可以使用 useEffect 预加载图像你的浏览器会缓存来自服务器的响应当你使用相同的 URL 请求相同的图像时浏览器会从缓存中获取该图像而且这样可以给你的浏览器一些毫秒来渲染新图像然后你可以切换加载状态

const [isLoading, setIsLoading] = useState(true);
const [cachedImageUrl, setCachedImageUrl] = useState("");

useEffect(() => {
  setIsLoading(true);
  const image = new Image();

  image.onload = () => {
    setCachedImageUrl(src);
    const renderedInterval = setTimeout(() => setIsLoading(false), 100);
  }

  image.src = src;

  return () => {
    image.onload = () => {}
    clearInterval(renderedInterval);
  }
}, [src]);

return (
  <div className={styles.wrapper} style={{ opacity: isLoading ? "0.3" : "1" }}>
    <img src={cachedImageUrl} />
    <div>
      {isLoading && (
        <div className={styles.overlayLoading}>
          加载中...
        </div>
      )}
    </div>
  </div>
);

希望这有所帮助!如果有任何其他问题,请随时提出。

英文:

You can preload image with useEffect, your browser will cache response from server, and when you will request same image with same url, browser will take that image from cache. And also you give your browser some milliseconds to render a new image and then you can toggle loading state.

  const [isLoading, setIsLoading] = useState(true);
  const [cachedImageUrl, setCachedImageUrl] = useState(&quot;&quot;);

  useEffect(() =&gt; {
   setIsLoading(true);
   const image = new Image();

   image.onload = () =&gt; {
     setCachedImageUrl(src);
     const renderedInterval = setTimeout(() =&gt; setIsLoading(false), 100);
   }

   image.src = src;

   return () =&gt; {
     image.onload = ()=&gt;{}
     clearInterval(renderedInterval); 
   }
  }, [src]);

  return (
    &lt;div className={styles.wrapper} style={{ opacity: isLoading ? &quot;0.3&quot; : &quot;1&quot; }}&gt;
    &lt;img src={cachedImageUrl} /&gt;
    &lt;div&gt;
      {isLoading &amp;&amp; (
        &lt;div className={styles.overlayLoading}&gt;
          Loading...
        &lt;/div&gt;
      )}
    &lt;/div&gt;
  &lt;/div&gt;
  );

答案2

得分: 1

我不知道您对RTK查询有多熟悉,但它似乎是最适合这项工作的工具。RTK查询在间隔抓取方面表现最佳。

查看这个示例和这个返回值。

注意:下面的代码尚未经过测试。

现在在您的情况下,您可以像这样做:

const { currentData, error, refetch, isFetching } = useGetImageQuery(name, {
  pollingInterval: 60000,
});

<div className={styles.wrapper} style={{ opacity: isFetching ? "0.3" : "1" }}>
  <img src={currentData.src} />
  <div>
    {isFetching && (
      <div className={styles.overlayLoading}>
        Loading...
      </div>
    )}
  </div>
</div>
英文:

I don't know how familiar you are with RTK query but it seems like it's the best tool for the job. RTK query works best with interval fetching.

Check out this example and this return value.

Note: below code has not been tested.

Now in your case, you can do something like:

const { currentData, error, refetch, isFetching } = useGetImageQuery(name, {
pollingInterval: 60000,
})

&lt;div className={styles.wrapper} style={{ opacity: isFetching ? &quot;0.3&quot; : &quot;1&quot; }}&gt;
  &lt;img src={currentData.src} /&gt;
  &lt;div&gt;
    {isFetching &amp;&amp; (
      &lt;div className={styles.overlayLoading}&gt;
        Loading...
      &lt;/div&gt;
    )}
  &lt;/div&gt;
&lt;/div&gt;

答案3

得分: 0

你需要创建一个额外的隐藏img标签,用它来加载新的图像,然后当onload事件触发时,你可以切换现有img标签的src属性到新图像,这将立即更新,因为图像现在已经在本地缓存中。

如何做这个操作的一些示例可以在这个问题中找到:https://stackoverflow.com/q/9582216/2087070

英文:

You need to create an extra hidden img tag that you use to load the new image, then when the onload event fires, you can switch the src attribute in the existing img tag to the new image, which will update straight away, as the image is now locally cached.

A few examples on how to do this can be found on this question https://stackoverflow.com/q/9582216/2087070

huangapple
  • 本文由 发表于 2023年3月10日 00:39:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687549.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定