Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Property onLoad$ of img tag not working with browser cache #4481

Closed
nanreh-dev opened this issue Jun 13, 2023 · 6 comments
Closed

Property onLoad$ of img tag not working with browser cache #4481

nanreh-dev opened this issue Jun 13, 2023 · 6 comments
Labels
STATUS-1: needs triage New issue which needs to be triaged TYPE: bug Something isn't working

Comments

@nanreh-dev
Copy link

Which component is affected?

Qwik Runtime

Describe the bug

I have a simple component with a jsx img tag where I use the onLoad$ property to render conditionally depending on whether the image is loaded or not. The issue is that when the image is cached in the browser the property doesn't work. In a browser with "private window" tab and cache off it works perfectly.
This happens in both Firefox and Chrome
If it helps i leave the code.

import { component$, useSignal, useTask$ } from "@builder.io/qwik";

interface Props {
  id: number | string;
  size?: number;
  backImg?: boolean;
  isVisible?: boolean;
}

export const PokemonImage = component$(
  ({ id, size = 200, backImg = false, isVisible = true }: Props) => {
    const isLoad = useSignal(false);

    useTask$(({ track }) => {
      track(() => id); //como el useeffect, si id cambia se ejecuta lo de abajo
      isLoad.value = false;
    });

    return (
      <div
        class="flex items-center justify-center"
        style={{ height: `${size}px` }}
      >
        {!isLoad.value && <span>Cargando...</span>}
        <img
          src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${backImg ? "back/" : ""
            }${id}.png`}
          alt="Poke Sprite"
          style={{ width: `${size}px` }}
          onLoad$={() => isLoad.value = true}
          class={[
            {
              "hidden": !isLoad.value,
              "brightness-0": !isVisible,
            },
            "transition-all",
          ]}
        />
      </div>
    );
  }
);

Reproduction

no url

Steps to reproduce

No response

System Info

no output

Additional Information

No response

@nanreh-dev nanreh-dev added TYPE: bug Something isn't working STATUS-1: needs triage New issue which needs to be triaged labels Jun 13, 2023
@manucorporat
Copy link
Contributor

I guess when it's cached, the event is not dispatched on page load... not sure we can solve it from qwik

@manucorporat
Copy link
Contributor

maybe SSR iamges, you can just assumed they are loaded

@nanreh-dev
Copy link
Author

I guess when it's cached, the event is not dispatched on page load... not sure we can solve it from qwik

Hi, thanks for your qwik response.
Don't get me wrong, I'm just a javascript noob, but I understand that in REACT this works:

import React, { useState } from "react";

const Prueba = () => {
  const [imgLoaded, setImgLoaded] = useState(false);
  return (
    <div>
      {!imgLoaded && <p>Cargando...</p>}
      <img
        src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/50.png"
        alt=""
        onLoad={() => {
          console.log("CARGO");
          setImgLoaded(true);
        }}
      />
    </div>
  );
};

export default Prueba;

On the other hand, I have investigated and it seems that there is no function in the browser api that returns if the image comes from the cache or from the network.
Maybe in react they are using the time method, as explained here:
https://stackoverflow.com/questions/13556527/javascript-detect-if-image-is-in-cache
which if it is this way seems to be a pretty cheap trick.

Anyway, thanks for this wonderful framework, I really like the way it makes the developer's job so much easier 😉👍

@KenAKAFrosty
Copy link
Contributor

@hilonegro52 I think using the img element's decode method will be more reliable and accomplish the effect you want, with the nice added bonus that it's Promise-driven as well.

simple example, inside of some component$

    const imgRef = useSignal<HTMLImageElement>();
    useVisibleTask$(()=> { 
        imgRef.value!.decode().then(()=> { 
            console.log('loaded and ready!');
        })
    });
    
   //other logic etc
   return (<section>
       <img ref=[imgRef} srf="some-source.png" height={200} width={200} />
   </section>)

@nanreh-dev
Copy link
Author

@hilonegro52 I think using the img element's decode method will be more reliable and accomplish the effect you want, with the nice added bonus that it's Promise-driven as well.

simple example, inside of some component$

    const imgRef = useSignal<HTMLImageElement>();
    useVisibleTask$(()=> { 
        imgRef.value!.decode().then(()=> { 
            console.log('loaded and ready!');
        })
    });
    
   //other logic etc
   return (<section>
       <img ref=[imgRef} srf="some-source.png" height={200} width={200} />
   </section>)

good job!! It will definitely replace onLoad$ in everyday life.
Anyway, the reason I'm reporting this bug is more than anything to alert qwik developers about the onLoad$ property malfunction.

@PatrickJS
Copy link
Member

closing for #6246 where we need this as cookbook example

@PatrickJS PatrickJS closed this as not planned Won't fix, can't repro, duplicate, stale May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
STATUS-1: needs triage New issue which needs to be triaged TYPE: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants