skip to Main Content

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>

2

Answers


  1. Chosen as BEST ANSWER
    `const fetcher = (url: string, id: string) => {
     const urlWithQuery = ${url}/${id}/icon
     return fetch(urlWithQuery).then((res) => res.json())}`
    
    const { data, error, isLoading } = useSWR(
    ['/api/avatar', id],
    ([url, id]) => fetcher(url, id),
    {
      revalidateOnFocus: true
    }
    

    )


  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search