Search code examples
reactjsgatsbygatsby-image

How to tell if Gatsby Image component has loaded?


I have a GatsbyImage / StaticImage component and I use the onLoad event to trigger an animation. But once the browser has cached the image, the onLoad event never fires again. So if you visit a different page and then return, the animation isn't triggered.

The usual workaround with an ordinary image would be to attach a ref and then check ref.current.complete to see if the image had loaded. But GatsbyImage refuses to take a ref.

So

  1. Is there any way to add a ref to the GatsbyImage component?
  2. Is there any other way to detect if the image has loaded?
  3. Is the only alternative to use an ordinary img tag (and lose out on all the gatsby image magic)?

Solution

    1. Is there any way to add a ref to the GatsbyImage component?

    Apparently, you can't. According to this GitHub thread it throws the following exception:

    Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

    That said, you can try using forwardRef() which will give you a valid scope for your use-case.

    1. Is there any other way to detect if the image has loaded?

    Not directly. However, you can try the onStartLoad callback which expose the wasCached boolean that gives your more information and control about the browser cache. You can play around with that boolean to trigger the animation again or to use the value globally along with a useState for example:

    <GatsbyImage
      fadeIn={false}
      className="customImg"
      onLoad={() => {
        // do loading stuff
      }}
      onStartLoad={({ wasCached }) => {
        // do stuff on start of loading
        // optionally with the wasCached boolean parameter
      }}
      onError={(error) => {
        // do error stuff
      }}
    />
    
    1. Is the only alternative to use an ordinary img tag (and lose out on all the gatsby image magic)?

    You can find a bunch of dependencies to lazy-load, fade, blur, get background primary color, etc of an image but its implementation, behavior, and compatibility will rely on the library itself. So, yes, there are alternatives but I'm not sure if they are worth it.