Image: ignore changes to 'onLoad' callback if image already loaded
The problem The Image component reloads on each rerender.
How to reproduce https://codesandbox.io/s/happy-mountain-i2eol?file=/src/App.js
Steps to reproduce:
- Add the Image tag to your component
- Add the onLoad property to the Image tag
- set state in the onLoad property
Expected behavior
It would work similar to the img tag. Here is the same code sandbox with <Image swapped out for <img src= https://codesandbox.io/s/happy-bell-i4v5q?file=/src/App.js
Environment (include versions). Did this work in previous versions? Please see code sandbox. It did not work differently in a previous verion that I am aware of.
Disclaimer: My expectations and use case might not align with react native web. However I am not sure how to successfully set state in onLoad without a duplicate render.
Your code is creating a new onLoad function every time the onLoad function is called because the loadedCount dependency changes every time. This is an infinite loop you bail out of using the count condition.
You can reproduce the issue for img by setting the callback to ref instead of onLoad (which the browser only calls once): https://codesandbox.io/s/nifty-dewdney-vi8pe?file=/src/App.js
Arguably RNWeb should not call new onLoad functions if the image has already loaded, so I'll leave this open. But you should fix the loop in your code that is creating new functions on every state update.
thanks for the information @necolas.
Unfortunately in my app removing dependencies from the useCallback doesn't help. Even if I just use a plain old function like this it still renders twice.
const [isImageLoading, setIsImageLoading] = useState(true);
const onLoad = () => {
setIsImageLoading(false);
};
<Image
onLoad={onLoad}
source={{
uri:...
You're still creating a new onLoad function each time the state changes
ok moving the Image to its own component and passing onLoad as a prop seems to work. Thanks again. Looking forward to following this trough. I will be on standby for testing or anything else you might need don't hesitate to ask.
I picked this back up and realized my initial solution was not working as intended due to commented-out code. I am not sure how to set the loading state without causing a duplicate image load. I have tried moving the onLoad function into both the parent and child components with no luck.
@necolas Can you provide more detail on avoiding creating a new onLoad function every time the onLoad function is called. Is this possible while using setState in a functional component?
@oste is it what you want? https://codesandbox.io/s/loving-montalcini-f3ibo?file=/src/App.js
@MohammadAzimi That is precisely what I am trying to achieve. However, as I mentioned that solution doesn't work as well in my app. It actually results in an infinite loop of that same image loading. It would seem that one of these useEffect dependencies are changing but I am not sure which since I also have the uri hardcoded and the same onLoad function. https://github.com/necolas/react-native-web/blob/2d9dca42fa67d09de8ff2de323c622b47a820354/packages/react-native-web/src/exports/Image/index.js#L278
@oste I forked your codesandbox link and refactored to use a class component instead of hooks. This issue did not happen. If this is an option explore this path as well.