Search code examples
reactjsimagenext.jsfallbackreact-suspense

React suspense fallback retriggers


I have an image that I take from an API endpoint. For a reason, I'm importing the image component inside a Suspense with a fallback. The problem is that every time a useState or a useEffect is executed, the fallback of the Suspense is shown. Is there any way to prevent the Suspense fallback from being shown after the first render or when the image is cached?

 export async function AvatarIcon({ id }: { id: string }) {
  const avatarIcon = await getAvatarIcon(id)

  return (
    <div className="">
      <Image
        src={`data:image/png;base64, ${avatarIcon}`}
        height={40}
        width={40}
        className="relative z-0 h-full w-16"
        alt="Avatar Icon"
      ></Image>
    </div>
  )
}

The other component where I use Suspense:

<div>
  <Suspense fallback={<div></div>}>
    <AvatarIcon id={user.id} />
  </Suspense>
</div>

Solution

  • fallback is running because the default value of loading prop is "lazy". from docs

    The loading behavior of the image. Defaults to lazy.

    When lazy, defer loading the image until it reaches a calculated distance from the viewport.

    When eager, load the image immediately.

    if you change the loading="eager", this might work (I di not test it out) because the component is already loaded and ready to render. The Suspense component only shows its fallback content when the wrapped component is not ready to be rendered

    But I think that setting an "eager" option inside Suspense doesn't make sense because Suspense is specifically designed to handle components that load asynchronously.

    in this loader file, you can confire Caching Behavior :

    The following describes the caching algorithm for the default loader. For all other loaders, please refer to your cloud provider's documentation.

    Images are optimized dynamically upon request and stored in the /cache/images directory. The optimized image file will be served for subsequent requests until the expiration is reached. When a request is made that matches a cached but expired file, the expired image is served stale immediately. Then the image is optimized again in the background (also called revalidation) and saved to the cache with the new expiration date.

    The cache status of an image can be determined by reading the value of the x-nextjs-cache response header. The possible values are the following:

    • MISS - the path is not in the cache (occurs at most once, on the first visit)
    • STALE - the path is in the cache but exceeded the revalidate time so it will be updated in the background
    • HIT - the path is in the cache and has not exceeded the revalidate time The expiration (or rather Max Age) is defined by either the minimumCacheTTL configuration or the upstream image Cache-Control header, whichever is larger. Specifically, the max-age value of the Cache-Control header is used. If both s-maxage and max-age are found, then s-maxage is preferred. The max-age is also passed-through to any downstream clients including CDNs and browsers.

    You can configure minimumCacheTTL to increase the cache duration when the upstream image does not include Cache-Control header or the value is very low. You can configure deviceSizes and imageSizes to reduce the total number of possible generated images. You can configure formats to disable multiple formats in favor of a single image format.