-
Notifications
You must be signed in to change notification settings - Fork 26
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
Error fallback image with loadEagerly? #22
Comments
Hi @aralroca! Thanks for opening this issue. An important property there, is that it works immediately and without Javascript (the browser only ever sees an I think that observing the loading states with Having said that, this does make me consider that in cases where we render on the client with |
Hi @fpapado, thank you for the answer. In my case, I'm doing an e-commerce with Next.js In all the app I'm loading the images with the lazy way (widgets and lists) using your library. And everywhere is working fine, loading the fallback image if this image is broken (using the error prop). However, in the only place that I want to load the image asap, is in the product page. In this case I used the prop I try it to do a workaround, doing something similar to: <LazyImage
loadEagerly
src={src}
alt=""
actual={({ imageProps }) => (
<img
onError={onErrorImage}
{...imageProps}
/>
)}
/> and: function onErrorImage(e) {
e.target.src = fallbackSrc
} And this works in some cases :) . With CSR this workaround works 100% well. Nevertheless, I realized that sometimes is not firing the |
I just realized that I can pass the Doing this I have a similar result than the workaround. Rendering the fallback image if is broken... However in the Rehydration moment is blinking... If the image is broken, maybe make sense because is replacing the broken image to the fallback image. But if the image is not broken, is doing some rare blinking effect. |
I think the workaround that you mention with The second scenario with The reason the workaround only works sometimes, as far as I can tell, is that the event could fire before the client scripts have downloaded/parsed/executed. I don't think it's Next.js specific, but rather how hydration and events work. I could be wrong though! A potential solutionThis discussion does give me an idea:
In theory, this means:
I have some free time over the next few days, and was looking into tackling some leftover issues here. I'll let you know if I manage to get a beta version out. No guarantees that it'll work, but we can try it and get some feedback :) |
@fpapado currently I'm using the first workaround that I commented, with useEffect(() => {
if (imageRef && imageRef.current) {
const { complete, naturalHeight } = imageRef.current
const errorLoadingImgBeforeHydration = complete && naturalHeight === 0
if (errorLoadingImgBeforeHydration) {
imageRef.current.src = fallbackSrc
}
}
}, []) I expect that always that image is completed with naturalHeight as 0, is broken. It's not an elegant solution. However, it works. |
Better detailed: hook: import { useRef, useCallback, useEffect } from 'react'
import noop from 'lodash/noop'
/**
* Using loadEagerly, with SSR the image is displayed ASAP,
* in the first render.
*
* With loadEagerly activated, the "error" prop of LazyImage
* component is not rendering. So, in order to workaround the fallback image,
* I need to do two things:
*
* * Catch the event onError and change the src with the fallback image
* * Check in the "didMount" (useEffect) that if is completed and doesn't
* have height, this means that there is an error, and how is completed
* before the hydration, the onError event was not fired by React. So in
* this case also the src shoud be changed to the fallback image.
*/
export default function useLoadEagerlyFallbackImage(fallbackSrc) {
const ref = useRef(null)
/**
* Error happened / catched after hydration
*/
const onError = useCallback(
e => { e.target.src = fallbackSrc }, [fallbackSrc],
)
/**
* Error happened before hydration, but catched after hydration
*/
useEffect(() => {
if (ref && ref.current) {
const { complete, naturalHeight } = ref.current
const errorLoadingImgBeforeHydration = complete && naturalHeight === 0
if (errorLoadingImgBeforeHydration) {
ref.current.src = fallbackSrc
}
}
}, [fallbackSrc])
return { ref, onError }
} Usage: const loadEagerlyProps = useLoadEagerlyFallbackImage(fallbackSrc)
return (
<LazyImage
loadEagerly
src={src}
alt=""
actual={({ imageProps }) => (
<img {...imageProps} {...loadEagerlyProps} />
)}
/>
) |
I need an image that should be rendered asap (I'm using SSR with next.js), and currently I'm using the
loadEagerly
prop in this image... However, I found interesting that if for some reason this image doesn't exist, display the fallback image... Looks that with loadEagerly is only rendering the actual.There is some another option to do it?
The text was updated successfully, but these errors were encountered: